package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.after.sale.api.model.constant.AgentFlagEnum;
import com.ssy.lingxi.after.sale.api.model.vo.request.*;
import com.ssy.lingxi.after.sale.api.model.vo.response.ReturnGoodsDetailListResponse;
import com.ssy.lingxi.after.sale.api.model.vo.response.ReturnGoodsInfoVO;
import com.ssy.lingxi.after.sale.api.model.vo.response.ReturnGoodsTaxVO;
import com.ssy.lingxi.after.sale.constant.Constants;
import com.ssy.lingxi.after.sale.entity.*;
import com.ssy.lingxi.after.sale.model.bo.EvaluateBO;
import com.ssy.lingxi.after.sale.model.bo.ReceiveGoodsBO;
import com.ssy.lingxi.after.sale.model.bo.ReturnReceiveGoodsBO;
import com.ssy.lingxi.after.sale.model.constant.*;
import com.ssy.lingxi.after.sale.model.vo.request.*;
import com.ssy.lingxi.after.sale.model.vo.response.*;
import com.ssy.lingxi.after.sale.repository.*;
import com.ssy.lingxi.after.sale.service.*;
import com.ssy.lingxi.after.sale.utils.CodeUtils;
import com.ssy.lingxi.after.sale.utils.ParamVerifyUtils;
import com.ssy.lingxi.after.sale.utils.ProcessUtil;
import com.ssy.lingxi.common.constant.basic.UserLoginSourceEnum;
import com.ssy.lingxi.common.constant.member.MemberRoleEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderPayTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.constant.settle.SettlementOrderTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.contract.api.model.constant.ContractOrderTypeEnum;
import com.ssy.lingxi.contract.api.model.vo.request.ContractExecuteInfoAddVO;
import com.ssy.lingxi.dto.model.constant.SettleAccountQueueMessageTypeEnum;
import com.ssy.lingxi.dto.request.PlatformCouponSettlementDetailRequestVO;
import com.ssy.lingxi.dto.request.PlatformCouponSettlementRequestVO;
import com.ssy.lingxi.dto.request.SettlementOrderVO;
import com.ssy.lingxi.dto.request.SettlementProductVO;
import com.ssy.lingxi.marketing.api.model.constant.ActivityRecordTypeEnum;
import com.ssy.lingxi.marketing.api.model.constant.MkRedisKeyConstants;
import com.ssy.lingxi.marketing.api.model.request.GoodsSalesItemReq;
import com.ssy.lingxi.marketing.api.model.request.GoodsSalesReq;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignAfterSaleCommentVO;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.*;
import com.ssy.lingxi.order.api.model.vo.response.OrderAfterSalePaymentFeignDetailVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderAfterSaleProductFeignDetailVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderProductCouponFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderSettleAccountInvoiceFeignDetailVO;
import com.ssy.lingxi.pay.api.dto.request.assetAccount.BalanceRefundRequest;
import com.ssy.lingxi.pay.api.dto.request.eAccount.EAccountRefundRequest;
import com.ssy.lingxi.pay.api.feign.ICreditControllerFeign;
import com.ssy.lingxi.pay.api.model.vo.request.CreditRefundVO;
import com.ssy.lingxi.pay.api.model.vo.request.ccb.B2bRefundVO;
import com.ssy.lingxi.pay.api.model.vo.request.ccb.DigitalRefundVO;
import com.ssy.lingxi.pay.api.model.vo.response.allInPay.RefundRespVO;
import com.ssy.lingxi.report.api.enums.AfterSaleReturnApplyOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.AfterSaleReturnHandleOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.AfterSaleReturnPfHandleOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.workflow.api.model.contant.ProcessEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import lombok.val;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 售后退货接口服务实现
 * @author 伍将
 * @date 2020/9/4
 * @version 2.0.0
 */
@Service
public class ReturnGoodsServiceImpl implements IReturnGoodsService {

    private static final Logger logger = LoggerFactory.getLogger(ReturnGoodsServiceImpl.class);

    @Resource
    private ReturnGoodsRepository returnRepository;

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private ReturnGoodsDetailRepository returnGoodsDetailRepository;

    @Resource
    private EvaluateRepository evaluateRepository;

    @Resource
    private OuterWorkflowRecordRepository outerWorkflowRecordRepository;

    @Resource
    private InnerWorkflowRecordRepository innerWorkflowRecordRepository;

    @Resource
    private IEvaluateService evaluateService;

    @Resource
    private IInnerWorkflowRecordService innerWorkflowRecordService;

    @Resource
    private IOuterWorkflowRecordService outerWorkflowRecordService;

    @Resource
    private ReturnDeliveryGoodsRepository returnDeliveryGoodsRepository;
    @Resource
    private ReturnDeliveryGoodsDetailRepository returnDeliveryGoodsDetailRepository;

    @Resource
    private ReturnGoodsRefundDetailRepository returnGoodsRefundDetailRepository;
    @Resource
    private ReturnGoodsDetailMaterielRepository returnGoodsDetailMaterielRepository;

    @Resource
    private IFeignService feignService;

    @Resource
    private IReturnDeliveryGoodsService returnDeliveryGoodsService;

    @Resource
    private IReturnGoodsDetailService returnGoodsDetailService;

    @Resource
    private ReturnManualDeliveryGoodsRepository returnManualDeliveryGoodsRepository;

    @Resource
    private ICreditControllerFeign creditControllerFeign;

/*    @Resource
    private InvoicesControllerFeign invoicesControllerFeign;*/

//    @Resource
//    private ContractExecuteControllerFeign contractExecuteControllerFeign;

    //直接注入使用QueryDsl
    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private IProcessFeignService processFeignService;
    @Autowired
    private IRedisStringUtils redisStringUtils;
    /**
     * 分页查询维退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyQueryVO>>
     **/
    private Wrapper<PageData<ReturnGoodsQueryVO>> pageList(ReturnGoodsPageVO pageVO, Boolean isSupplierSel, Long memberId, Long roleId) {

        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (isSupplierSel) {
                list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), memberId));
                list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), roleId));
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("outerStatus").as(Integer.class), ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode()));
            } else {
                list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), memberId));
                list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), roleId));
            }
            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (pageVO.getInnerStatus() != null
                    && !pageVO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), isSupplierSel);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 转换退货申请查询VO
     * @author 伍将
     * @date 2020/9/4 退货申请表
     * @param returnGoodsDOList:退货申请单
     * @param isSupplier: 是否为服务提供者
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyQueryVO>
     **/
    private List<ReturnGoodsQueryVO> ConvertReturnGoodsApplyQueryVO(List<ReturnGoodsDO> returnGoodsDOList, Boolean isSupplier) {
        List<ReturnGoodsQueryVO> resultList = null;
        if (returnGoodsDOList != null) {
            resultList = returnGoodsDOList.stream().map(r -> {
                ReturnGoodsQueryVO queryVO = new ReturnGoodsQueryVO();
                queryVO.setReturnId(r.getId());
                queryVO.setApplyNo(r.getApplyNo());
                queryVO.setApplyAbstract(r.getApplyAbstract());
                queryVO.setConsumerName(r.getConsumerName());
                queryVO.setSupplierName(r.getSupplierName());
                queryVO.setRefundAmount(r.getRefundAmount());
                queryVO.setRefunded(r.getRefunded());
                queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
                queryVO.setInnerStatus(r.getInnerStatus());
                if (!isSupplier && ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(r.getOuterStatus())) {
                    queryVO.setInnerStatusName( RepairGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getConsumerDescribe());
                } else if (!isSupplier && ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(r.getOuterStatus())) {
                    queryVO.setInnerStatusName(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getMessage());
                } else {
                    queryVO.setInnerStatusName(ReturnGoodsInnerStatusEnum.getDescribe(r.getInnerStatus(), isSupplier));
                }
                if(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode().equals(r.getOuterStatus())){
                    queryVO.setInnerStatusName(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getMessage());
                }
                queryVO.setOuterStatus(r.getOuterStatus());
                queryVO.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(r.getOuterStatus()));
                queryVO.setReturnBatch(r.getReturnBatch());
                queryVO.setReturnDeliveryId(r.getReturnDeliveryId());
                queryVO.setReturnDeliveryNo(r.getReturnDeliveryNo());
                queryVO.setReturnStorageId(r.getReturnStorageId());
                queryVO.setReturnStorageNo(r.getReturnStorageNo());
                queryVO.setReturnLogisticsId(r.getReturnLogisticsId());
                queryVO.setReturnLogisticsNo(r.getReturnLogisticsNo());
                queryVO.setReturnGoodsAddress(r.getReturnGoodsAddress());
                queryVO.setMemberId(r.getMemberId());
                queryVO.setRoleId(r.getRoleId());
                queryVO.setParentMemberId(r.getParentMemberId());
                queryVO.setParentMemberRoleId(r.getParentMemberRoleId());
                queryVO.setShopId(r.getShopId());
                queryVO.setShopLogo(r.getShopLogo());
                queryVO.setShopName(r.getShopName());
                return queryVO;
            }).collect(Collectors.toList());
        }

        return resultList;
    }

    /**
     * 根据退货单id，获得物料
     * @param returnId 退货单id
     * @return 物料
     */
    private Map<Long, ReturnGoodsDetailAssociatedDO> getMaterielListByReturnId(Long returnId){
        Map<Long, ReturnGoodsDetailAssociatedDO> materielDOMap=null;
            List<ReturnGoodsDetailAssociatedDO> byReturnId = returnGoodsDetailMaterielRepository.findByReturnId(returnId);
            if(CollectionUtil.isNotEmpty(byReturnId)){
                materielDOMap= byReturnId.stream().collect(Collectors.toMap(ReturnGoodsDetailAssociatedDO::getReturnDetailId, o -> o));
            }
        return materielDOMap;
    }
    /**
     * 获取退货详情
     * @author 伍将
     * @date 2020/9/4
     * @param returnId:
     * @param isSupplier:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyDetailVO>
     **/
    private Wrapper<ReturnGoodsDetailVO> getDetail(UserLoginCacheDTO user, Long returnId, Boolean isSupplier) {

        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        ReturnGoodsDetailVO result = new ReturnGoodsDetailVO();

        // 组装基础信息
        result.setReturnId(returnDO.getId());
        result.setApplyNo(returnDO.getApplyNo());
        result.setApplyAbstract(returnDO.getApplyAbstract());
        result.setConsumerName(returnDO.getConsumerName());
        result.setMemberId(returnDO.getMemberId());
        result.setRoleId(returnDO.getRoleId());
        result.setSupplierName(returnDO.getSupplierName());
        result.setParentMemberId(returnDO.getParentMemberId());
        result.setParentMemberRoleId(returnDO.getParentMemberRoleId());
        result.setApplyTime(DateUtil.format(DateUtil.date(returnDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        result.setOuterStatus(returnDO.getOuterStatus());
        result.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()));
        result.setInnerStatus(returnDO.getInnerStatus());
        result.setReturnReason(returnDO.getReturnReason());
        result.setShopId(returnDO.getShopId());
        result.setShopLogo(returnDO.getShopLogo());
        result.setShopName(returnDO.getShopName());
        // 设置代客标识
        result.setAgentFlag(Optional.ofNullable(returnDO.getAgentFlag()).orElse(AgentFlagEnum.NOT.getCode()));

        if (!isSupplier && ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(returnDO.getOuterStatus())) {
            result.setInnerStatusName(RepairGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getConsumerDescribe());
        } else if (!isSupplier && ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(returnDO.getOuterStatus())) {
            result.setInnerStatusName(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getMessage());
        } else {
            result.setInnerStatusName(ReturnGoodsInnerStatusEnum.getDescribe(returnDO.getInnerStatus(), isSupplier));
        }
        result.setTaskType(returnDO.getOuterTaskType());
        result.setTaskTypeKey(ProcessEnum.getProcessKeyByCode(returnDO.getOuterTaskType()));
        result.setFaultFileList(returnDO.getProofFileList());
        result.setReturnGoodsAddress(returnDO.getReturnGoodsAddress());
        result.setReturnBatch(returnDO.getReturnBatch());
        result.setOrderType(returnDO.getOrderType());

        // 组装评价
        Wrapper<EvaluateBO> evaluateWrapper = evaluateService.getDetail(returnId, AfterSaleTypeEnum.RETURN.getCode());
        if (evaluateWrapper == null) {
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(evaluateWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(evaluateWrapper);
        }
        result.setEvaluate(evaluateWrapper.getData());

        // 组装外部单据流转记录
        Wrapper<List<ReturnOuterWorkflowRecordVO>> outerRecordWrapper = outerWorkflowRecordService.getReturnRecordList(returnId);
        if (outerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(outerRecordWrapper);
        }
        result.setOuterRecordList(outerRecordWrapper.getData());

        // 组装外部流转
        List<TaskStepVO> outerTaskList = processFeignService.listTaskStepOut(returnDO.getOuterTaskType(), returnDO.getOuterTaskId(), returnDO.getRoleId(), returnDO.getParentMemberRoleId());
        result.setOuterTaskList(outerTaskList);


        // 组装内部单据流转记录
        Wrapper<List<ReturnInnerWorkflowRecordVO>> innerRecordWrapper = innerWorkflowRecordService.getReturnRecordList(user.getMemberId(), user.getMemberRoleId(), returnId);
        if(innerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(innerRecordWrapper);
        }
        result.setInnerRecordList(innerRecordWrapper.getData());

        // 组装内部流转
        if (isSupplier) {
            List<TaskStepVO> innerTaskList = processFeignService.listTaskStep(returnDO.getInnerTaskType(), returnDO.getInnerTaskId(), returnDO.getMemberId());
            result.setInnerTaskList(innerTaskList);
        }
        //查询物料信息
        Map<Long, ReturnGoodsDetailAssociatedDO> materielListByReturnId=null;
        if(ParamVerifyUtils.isContractOrderType(returnDO.getOrderType())) {
            materielListByReturnId = getMaterielListByReturnId(returnId);
        }
        final Map<Long, ReturnGoodsDetailAssociatedDO> materielDOMap=materielListByReturnId;
        List<ReturnGoodsDetailDO> returnGoodsDetailDOList = returnGoodsDetailRepository.findByReturnId(returnId);
        if (returnGoodsDetailDOList != null && returnGoodsDetailDOList.size() > 0) {
            // 退货明细
            List<ReturnGoodsDetailQueryVO> goodsDetailList = returnGoodsDetailDOList.stream().map(r -> {
                ReturnGoodsDetailQueryVO queryVO = new ReturnGoodsDetailQueryVO();
                queryVO.setReturnDetailId(r.getId());
                queryVO.setOrderId(r.getOrderId());
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setOrderRecordId(r.getOrderRecordId());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setPurchaseCount(r.getPurchaseCount());
                queryVO.setPurchasePrice(r.getPurchasePrice());
                queryVO.setPurchaseAmount(NumberUtil.mul(r.getPurchaseCount() , r.getPurchasePrice()));
                queryVO.setPayAmount(r.getPayAmount());
                queryVO.setReturnCount(r.getReturnCount());
                queryVO.setRefundAmount(r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).reduce(0D, NumberUtil::add));
                queryVO.setReturnReason(r.getReturnReason());
                queryVO.setIsNeedReturn(r.getIsNeedReturn());
                queryVO.setNeedReturnName(CommonBooleanEnum.getMessage(r.getIsNeedReturn()));
                queryVO.setType(r.getType());
                queryVO.setDeliveryCount(r.getDeliveryCount());
                queryVO.setNoDeliveryCount(NumberUtil.sub(r.getReturnCount(),r.getDeliveryCount()));
                queryVO.setReceiveCount(r.getReceiveCount());
                queryVO.setSubCount(NumberUtil.sub(r.getDeliveryCount(),r.getReceiveCount()));
                queryVO.setIsHasTax(r.getIsHasTax());
                queryVO.setTaxRate(r.getTaxRate());
                queryVO.setContractId(r.getContractId());
                queryVO.setContractNo(r.getContractNo());
                queryVO.setSkuId(r.getSkuId());
                queryVO.setSkuPic(r.getSkuPic());
                if(materielDOMap!=null){
                    ReturnGoodsDetailAssociatedDO materielDO = materielDOMap.get(r.getId());
                    if(materielDO!=null) {
                        queryVO.setAssociatedUnit(materielDO.getUnit());
                        queryVO.setAssociatedCategory(materielDO.getCategory());
                        queryVO.setAssociatedBrand(materielDO.getBrand());
                        queryVO.setAssociatedProductName(materielDO.getProductName());
                        queryVO.setAssociatedProductId(materielDO.getProductId());
                        queryVO.setAssociatedType(materielDO.getType());
                    }
                }
                if (r.getRefundList() != null) {
                    List<ReturnGoodsPayVO> payVOList = r.getRefundList().stream().map(o -> {
                        ReturnGoodsPayVO entity = new ReturnGoodsPayVO();
                        entity.setPayId(o.getPayId());
                        entity.setExternalState(o.getExternalState());
                        entity.setPayCount(o.getPayCount());
                        entity.setPayNode(o.getPayNode());
                        entity.setPayRatio(o.getPayRatio());
                        entity.setPayAmount(o.getPayAmount());
                        entity.setPayWay(o.getPayWay());
                        entity.setPayWayName(OrderPayTypeEnum.getNameByCode(o.getPayWay()));
                        entity.setChannel(o.getChannel());
                        entity.setChannelName(OrderPayChannelEnum.getNameByCode(o.getChannel()));
                        entity.setRefundAmount(o.getRefundAmount());
                        entity.setPayTime((o.getPayTime() != null && o.getPayTime() > 0) ? DateUtil.format(DateUtil.date(o.getPayTime()), "yyyy-MM-dd HH:mm") : "");
                        entity.setTransactionPayId(o.getTransactionPayId());
                        return entity;
                    }).collect(Collectors.toList());
                    queryVO.setPayList(payVOList);
                }
                return queryVO;
            }).collect(Collectors.toList());
            result.setGoodsDetailList(goodsDetailList);

            // 退货统计
            List<ReturnGoodsStatisticsVO> goodsStatisticsList = returnGoodsDetailDOList.stream().map(r -> {
                ReturnGoodsStatisticsVO queryVO = new ReturnGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReturnCount(r.getReturnCount());
                queryVO.setDeliveryCount(r.getDeliveryCount());
                queryVO.setUnDeliveryCount(NumberUtil.sub(r.getReturnCount() ,r.getDeliveryCount()));
                queryVO.setReceiveCount(r.getReceiveCount());
                queryVO.setDifferenceCount(NumberUtil.sub(r.getDeliveryCount() , r.getReceiveCount()));
                return queryVO;
            }).collect(Collectors.toList());
            result.setReturnStatisticsList(goodsStatisticsList);

            // 退货明细
            List<DeliveryGoodsVO> deliveryGoodsVOList = returnDeliveryGoodsService.getDeliveryList(returnId, isSupplier);
            result.setReturnDeliveryGoodsList(deliveryGoodsVOList);

            // 退款明细
            List<ReturnGoodsRefundVO> refundList = returnGoodsDetailService.getDetailList(user, returnDO, returnId);
            result.setRefundList(refundList);
        }

        // 获取手工发货/退货信息 [废弃：731]
 /*       ReturnManualDeliveryGoodsDO manualDeliveryGoodsDO = returnManualDeliveryGoodsRepository.findByReturnId(returnId);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsVO deliveryGoodsVO = new ManualDeliveryGoodsVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(DateUtil.format(DateUtil.date(manualDeliveryGoodsDO.getDeliveryTime()), "yyyy-MM-dd HH:mm"));
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReturnGoodsAddress(deliveryGoodsVO);
        }*/

        return Wrapper.success(result);
    }

    /**
     * 消费者分页查询退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user: 当前登录用户
     * @param pageVO: 分页查询请求参数
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageByConsumer(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(pageVO.getInnerStatus());
        returnGoodsPageVO.setOuterStatus(pageVO.getOuterStatus());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    @Override
    public Wrapper<PageData<ReturnGoodsQueryAppVO>> pageByConsumerApp(UserLoginCacheDTO user, ReturnGoodsPageAppVO pageVO) {

        QReturnGoodsDO returnDO=QReturnGoodsDO.returnGoodsDO;
        QReturnGoodsDetailDO goodsDetailDO=QReturnGoodsDetailDO.returnGoodsDetailDO;

        //Step 1: 定义关联关系，OrderDO表必须要有distinct()
        JPAQuery<?> query = jpaQueryFactory.from(returnDO).distinct()
                .leftJoin(goodsDetailDO).on(returnDO.id.eq(goodsDetailDO.returnId))
                .where(returnDO.memberId.eq(user.getMemberId()).and(returnDO.roleId.eq(user.getMemberRoleId())));
        //外部状态
        if(pageVO.getOuterStatus()!=null) {
            query.where(returnDO.outerStatus.eq(pageVO.getOuterStatus()));
        }
        //内部状态
        if(pageVO.getInnerStatus()!=null) {
            query.where(returnDO.innerStatus.eq(pageVO.getInnerStatus()));
        }
        //申请时间
        if (StringUtils.hasLength(pageVO.getStartTime())) {
            query.where(returnDO.applyTime.goe(DateUtil.parse(pageVO.getStartTime()).getTime()));
        }
        if (StringUtils.hasLength(pageVO.getEndTime())) {
            DateTime endOfDay = DateUtil.endOfDay(DateUtil.parse(pageVO.getEndTime()));
            query.where(returnDO.applyTime.loe(endOfDay.getTime()));
        }
        //关键词
        if (StringUtils.hasLength(pageVO.getKeyword())) {
            query.where(goodsDetailDO.productName.like("%" +pageVO.getKeyword() +"%").or(goodsDetailDO.orderNo.like("%" +pageVO.getKeyword() +"%")).or(returnDO.applyNo.like("%" +pageVO.getKeyword() +"%")));
        }
        //Step 4: 倒序排序、分页、总数
        query.orderBy(returnDO.id.desc());
        query.limit(pageVO.getPageSize()).offset((pageVO.getCurrentOffset()));
        long totalCount = query.fetchCount();

        //Step 1: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, ReturnGoodsQueryAppVO> transform = query.transform(GroupBy.groupBy(returnDO.id).as(
                Projections.constructor(ReturnGoodsQueryAppVO.class, returnDO.id, returnDO.applyNo, returnDO.refundAmount, returnDO.innerStatus, returnDO.outerStatus, returnDO.shopId, returnDO.shopLogo, returnDO.shopName, returnDO.returnLogisticsId, returnDO.returnDeliveryId)));
        //Step 2:查询商品图片
        List<ReturnGoodsDetailDO> goodsDetailDOS = returnGoodsDetailRepository.findByReturnIdIn(transform.keySet());
        if(CollectionUtil.isNotEmpty(goodsDetailDOS)){
            goodsDetailDOS.forEach(o ->{
                ReturnGoodsQueryAppVO returnGoodsQueryAppVO = transform.get(o.getReturnId());
                if(returnGoodsQueryAppVO!=null){
                    List<ReturnGoodsQueryProductAppVO> productList = returnGoodsQueryAppVO.getProductList();
                    if(productList==null){
                        productList=new ArrayList<>();
                        returnGoodsQueryAppVO.setProductList(productList);
                    }
                    ReturnGoodsQueryProductAppVO vo=new ReturnGoodsQueryProductAppVO();
                    BeanUtils.copyProperties(o,vo);
                    productList.add(vo);
                }
            });
        }
        return Wrapper.success(new PageData<>(totalCount, new ArrayList<>(transform.values())));
    }

    /**
     * 消费者分页查询等待提交的退货
     * @author 伍将
     * @date 2020/9/10
     * @param user: 
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeSubmitByConsumer(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {

        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));

            // 查询外部状态为待提交或不接受申请的
            List<Integer> outerStatusList = new ArrayList<>();
            outerStatusList.add(ReturnGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode());
            outerStatusList.add(ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode());
            list.add(criteriaBuilder.in(root.get("outerStatus")).value(outerStatusList));

            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), false);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 消费者获取退货申请详情
     * @author 伍将
     * @date 2020/9/4
     * @param user: 
     * @param returnId: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyDetailVO>
     **/
    @Override
    public Wrapper<ReturnGoodsDetailVO> getDetailByConsumer(UserLoginCacheDTO user, Long returnId) {
        return getDetail(user, returnId, false);
    }

    /**
     * App端获取退货详情
     * @author 伍将
     * @date 2021/3/18
     * @param user: 当前登录用户
     * @param returnId: 退货id
     * @return 操作结果
     **/
    @Override
    public Wrapper<ReturnGoodsDetailAppVO> getDetailByApp(UserLoginCacheDTO user, Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        ReturnGoodsDetailAppVO result = new ReturnGoodsDetailAppVO();

        // 组装基础信息
        result.setReturnId(returnDO.getId());
        result.setApplyNo(returnDO.getApplyNo());
        result.setApplyAbstract(returnDO.getApplyAbstract());
        result.setConsumerName(returnDO.getConsumerName());
        result.setMemberId(returnDO.getMemberId());
        result.setRoleId(returnDO.getRoleId());
        result.setSupplierName(returnDO.getSupplierName());
        result.setParentMemberId(returnDO.getParentMemberId());
        result.setParentMemberRoleId(returnDO.getParentMemberRoleId());
        result.setApplyTime(DateUtil.format(DateUtil.date(returnDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        result.setOuterStatus(returnDO.getOuterStatus());
        result.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()));
        result.setInnerStatus(returnDO.getInnerStatus());
        result.setReturnReason(returnDO.getReturnReason());
        result.setShopName(returnDO.getShopName());
        if (ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(returnDO.getOuterStatus())) {
            result.setInnerStatusName(RepairGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getConsumerDescribe());
        } else if (ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(returnDO.getOuterStatus())) {
            result.setInnerStatusName(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getMessage());
        } else {
            result.setInnerStatusName(ReturnGoodsInnerStatusEnum.getDescribe(returnDO.getInnerStatus(), false));
        }
        result.setTaskType(returnDO.getOuterTaskType());
        result.setFaultFileList(returnDO.getProofFileList());
        result.setReturnGoodsAddress(returnDO.getReturnGoodsAddress());
        result.setReturnBatch(returnDO.getReturnBatch());

        // 组装评价
        Wrapper<EvaluateBO> evaluateWrapper = evaluateService.getDetail(returnId, AfterSaleTypeEnum.RETURN.getCode());
        if (evaluateWrapper == null) {
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(evaluateWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(evaluateWrapper);
        }
        result.setEvaluate(evaluateWrapper.getData());

        // 组装外部单据流转记录
        Wrapper<List<ReturnOuterWorkflowRecordVO>> outerRecordWrapper = outerWorkflowRecordService.getReturnRecordList(returnId);
        if (outerRecordWrapper == null) {
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(outerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(outerRecordWrapper);
        }
        result.setOuterRecordList(outerRecordWrapper.getData());

        // 组装外部流转
        List<TaskStepVO> outerTaskList = processFeignService.listTaskStepOut(returnDO.getOuterTaskType(), returnDO.getOuterTaskId(), returnDO.getRoleId(), returnDO.getParentMemberRoleId());
        result.setOuterTaskList(outerTaskList);

        // 组装内部单据流转记录
        Wrapper<List<ReturnInnerWorkflowRecordVO>> innerRecordWrapper = innerWorkflowRecordService.getReturnRecordList(user.getMemberId(), user.getMemberRoleId(), returnId);
        if (innerRecordWrapper == null) {
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(innerRecordWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(innerRecordWrapper);
        }
        result.setInnerRecordList(innerRecordWrapper.getData());

        Map<Long, ReturnGoodsDetailAssociatedDO> materielListByReturnId=null;
        if(ParamVerifyUtils.isContractOrderType(returnDO.getOrderType())) {
            materielListByReturnId = getMaterielListByReturnId(returnId);
        }
        final Map<Long, ReturnGoodsDetailAssociatedDO> materielDOMap=materielListByReturnId;
        List<ReturnGoodsDetailDO> returnGoodsDetailDOList = returnGoodsDetailRepository.findByReturnId(returnId);
        if (returnGoodsDetailDOList != null && returnGoodsDetailDOList.size() > 0) {
            // 退货明细
            List<ReturnGoodsDetailAppQueryVO> goodsDetailList = returnGoodsDetailDOList.stream().map(r -> {
                ReturnGoodsDetailAppQueryVO queryVO = new ReturnGoodsDetailAppQueryVO();
                queryVO.setReturnDetailId(r.getId());
                queryVO.setOrderId(r.getOrderId());
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setOrderRecordId(r.getOrderRecordId());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setPurchaseCount(r.getPurchaseCount());
                queryVO.setPurchasePrice(r.getPurchasePrice());
                queryVO.setPurchaseAmount(NumberUtil.mul(r.getPurchaseCount() , r.getPurchasePrice()));
                queryVO.setPayAmount(r.getPayAmount());
                queryVO.setReturnCount(r.getReturnCount());
                queryVO.setRefundAmount(r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).sum());
                queryVO.setReturnReason(r.getReturnReason());
                queryVO.setIsNeedReturn(r.getIsNeedReturn());
                queryVO.setNeedReturnName(CommonBooleanEnum.getMessage(r.getIsNeedReturn()));
                queryVO.setType(r.getType());
                queryVO.setDeliveryCount(r.getDeliveryCount());
                queryVO.setNoDeliveryCount(NumberUtil.sub(r.getReturnCount(),r.getDeliveryCount()));
                queryVO.setReceiveCount(r.getReceiveCount());
                queryVO.setSubCount(NumberUtil.sub(r.getDeliveryCount(),r.getReceiveCount()));
                queryVO.setSkuId(r.getSkuId());
                queryVO.setSkuPic(r.getSkuPic());
                if(materielDOMap!=null){
                    ReturnGoodsDetailAssociatedDO materielDO = materielDOMap.get(r.getId());
                    if(materielDO!=null){
                        BeanUtils.copyProperties(materielDO,queryVO);
                    }
                }
                if (r.getRefundList() != null) {
                    List<ReturnGoodsAppPayVO> payVOList = r.getRefundList().stream().map(o -> {
                        ReturnGoodsAppPayVO entity = new ReturnGoodsAppPayVO();
                        entity.setPayId(o.getPayId());
                        entity.setExternalState(o.getExternalState());
                        entity.setPayCount(o.getPayCount());
                        entity.setPayNode(o.getPayNode());
                        entity.setPayRatio(o.getPayRatio());
                        entity.setPayAmount(o.getPayAmount());
                        entity.setPayWay(o.getPayWay());
                        entity.setPayWayName(OrderPayTypeEnum.getNameByCode(o.getPayWay()));
                        entity.setChannel(o.getChannel());
                        entity.setChannelName(OrderPayChannelEnum.getNameByCode(o.getChannel()));
                        entity.setRefundAmount(o.getRefundAmount());
                        entity.setPayTime(o.getPayTime());
                        entity.setTransactionPayId(o.getTransactionPayId());
                        return entity;
                    }).collect(Collectors.toList());
                    queryVO.setPayList(payVOList);
                }
                return queryVO;
            }).collect(Collectors.toList());
            result.setGoodsDetailList(goodsDetailList);

            // 退货统计
            List<ReturnGoodsStatisticsVO> goodsStatisticsList = returnGoodsDetailDOList.stream().map(r -> {
                ReturnGoodsStatisticsVO queryVO = new ReturnGoodsStatisticsVO();
                queryVO.setOrderNo(r.getOrderNo());
                queryVO.setProductId(r.getProductId());
                queryVO.setProductName(r.getProductName());
                queryVO.setCategory(r.getCategory());
                queryVO.setBrand(r.getBrand());
                queryVO.setUnit(r.getUnit());
                queryVO.setReturnCount(r.getReturnCount());
                queryVO.setDeliveryCount(r.getDeliveryCount());
                queryVO.setUnDeliveryCount(NumberUtil.sub(r.getReturnCount() , r.getDeliveryCount()));
                queryVO.setReceiveCount(r.getReceiveCount());
                queryVO.setDifferenceCount(NumberUtil.sub(r.getDeliveryCount() , r.getReceiveCount()));
                return queryVO;
            }).collect(Collectors.toList());
            result.setReturnStatisticsList(goodsStatisticsList);

            // 退货明细
            List<DeliveryGoodsVO> deliveryGoodsVOList = returnDeliveryGoodsService.getDeliveryList(returnId, false);
            result.setReturnDeliveryGoodsList(deliveryGoodsVOList);

            // 退款明细
            List<ReturnGoodsRefundVO> refundList = returnGoodsDetailService.getDetailList(user, returnDO, returnId);
            result.setRefundList(refundList);
        }

        // 获取手工发货/退货信息 [废弃：731]
/*        ReturnManualDeliveryGoodsDO manualDeliveryGoodsDO = returnManualDeliveryGoodsRepository.findByReturnId(returnId);
        if (manualDeliveryGoodsDO != null) {
            ManualDeliveryGoodsAppVO deliveryGoodsVO = new ManualDeliveryGoodsAppVO();
            deliveryGoodsVO.setDataId(manualDeliveryGoodsDO.getId());
            deliveryGoodsVO.setDeliveryAddress(manualDeliveryGoodsDO.getDeliveryAddress());
            deliveryGoodsVO.setDeliveryTime(manualDeliveryGoodsDO.getDeliveryTime());
            deliveryGoodsVO.setLogisticsName(manualDeliveryGoodsDO.getLogisticsName());
            deliveryGoodsVO.setLogisticsOrderNo(manualDeliveryGoodsDO.getLogisticsOrderNo());
            result.setManualReturnGoodsAddress(deliveryGoodsVO);
        }*/

        return Wrapper.success(result);
    }

    /**
     * 校验订单-商品退货数量
     * @param saveVO 退货保存VO
     */
    private void checkReturnGoodsNum(ReturnGoodsSaveVO saveVO,Integer type,List<ReturnGoodsDetailDO> oldReturnGoodsDetailList,List<OrderAfterSaleProductFeignDetailVO> orderProductRecordList){
        Map<Long, OrderAfterSaleProductFeignDetailVO> orderGoodsMap = orderProductRecordList.stream().collect(Collectors.toMap(OrderAfterSaleProductFeignDetailVO::getOrderProductId, v -> v));
        Map<Long,Double> oldReturnGoodsCountMap=null;
        if(CollectionUtil.isNotEmpty(oldReturnGoodsDetailList)){
            oldReturnGoodsCountMap=oldReturnGoodsDetailList.stream().collect(Collectors.toMap(ReturnGoodsDetailDO::getOrderRecordId, ReturnGoodsDetailDO::getReturnCount));
        }
        for(ReturnGoodsDetailSaveVO goodsDetailSaveVO: saveVO.getReturnGoodsList()){
            OrderAfterSaleProductFeignDetailVO orderGood = orderGoodsMap.get(goodsDetailSaveVO.getOrderRecordId());
            if(orderGood==null){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PARAM_ERROR);
            }
            BigDecimal returnCount = orderGood.getReturnCount() != null ? orderGood.getReturnCount() : BigDecimal.ZERO;
            if(type==1) {//保存
                if (goodsDetailSaveVO.getReturnCount() > (NumberUtil.sub(orderGood.getQuantity(), returnCount).doubleValue())) {
                    String msg = String.format(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR.getMessage(), goodsDetailSaveVO.getOrderNo());
                    throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR, msg);
                }
            }else if(type==2){//更新
                Double oldReturnCount = oldReturnGoodsCountMap.get(goodsDetailSaveVO.getOrderRecordId());
                logger.info("goodsDetailSaveVO:{},returnCount:{},oldReturnCount:{}",goodsDetailSaveVO.getReturnCount(),returnCount,oldReturnCount);
                if(oldReturnCount!=null){//更新中，原保存项
                    //如果更改后退数>总采购数-(订单商品已申退-原申退数），则视为退票张数有误
                    if(goodsDetailSaveVO.getReturnCount() > (NumberUtil.sub(orderGood.getQuantity(),NumberUtil.sub(returnCount,BigDecimal.valueOf(oldReturnCount))).doubleValue())){
                        String msg = String.format(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR.getMessage(), goodsDetailSaveVO.getOrderNo());
                        throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR, msg);
                    }
                }else if (goodsDetailSaveVO.getReturnCount() > NumberUtil.sub(orderGood.getQuantity(),returnCount).doubleValue()) {//更新中，新增项
                    String msg = String.format(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR.getMessage(), goodsDetailSaveVO.getOrderNo());
                    throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PRODUCT_COUNT_PARAM_ERROR, msg);
                }
            }
        }
    }

    /**
     * 批量查询订单商品项支付记录
     * @param orderIds 订单id集合
     * @return 订单商品项支付记录
     */
    private Map<Long,List<OrderAfterSalePaymentFeignDetailVO>> getOrdersPayList(List<Long> orderIds){
        Wrapper<List<OrderAfterSalePaymentFeignDetailVO>> orderPayInfo = feignService.getOrderPayInfo(orderIds);
        if(orderPayInfo==null ||orderPayInfo.getCode()!=ResponseCode.SUCCESS.getCode() ){
            throw new BusinessException(ResponseCode.FEIGN_SERVICE_ERROR);
        }
        Map<Long,List<OrderAfterSalePaymentFeignDetailVO>> map=new HashMap<>();
        orderPayInfo.getData().forEach(o ->{
            List<OrderAfterSalePaymentFeignDetailVO> voList = map.get(o.getOrderId());
            if(voList==null){
                voList=new ArrayList<>();
                map.put(o.getOrderId(),voList);
            }
            voList.add(o);
        });
        return map;
    }

    /**
     * 根据订单记录ids，查询订单商品项信息
     * @param returnGoodsList 订单记录ids
     * @return 订单商品项信息
     */
    private List<OrderAfterSaleProductFeignDetailVO> getOrderProductRecordList(List<ReturnGoodsDetailSaveVO> returnGoodsList){
        //构建请求参数
        List<OrderProductIdFeignVO> collect = returnGoodsList.stream().map(o -> {
            OrderProductIdFeignVO vo = new OrderProductIdFeignVO();
            vo.setOrderProductId(o.getOrderRecordId());
            return vo;
        }).collect(Collectors.toList());
        //获取订单商品信息
        Wrapper<List<OrderAfterSaleProductFeignDetailVO>> listWrapper = feignService.afterSalesListById(collect);
        if (listWrapper == null || listWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.BUSINESS_ERROR);
        }
        List<OrderAfterSaleProductFeignDetailVO> data = listWrapper.getData();
        if(CollectionUtil.isEmpty(data)){
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PARAM_ERROR);
        }
        return data;
    }

    /**
     * 保存退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user:
     * @param saveVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<java.lang.Long>
     **/
    @Transactional
    @Override
    public Wrapper<Long> save(UserLoginCacheDTO user, ReturnGoodsSaveVO saveVO) {
        //转换工作流程key为code
        saveVO.setTaskType(ProcessEnum.getCodeByProcessKey(saveVO.getTaskTypeKey()));
        //校验
        if (!ProcessUtil.isReturnGoodsProcess(saveVO.getTaskType())) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_TYPE_UNDEFINED);
        }

        Map<Long, List<OrderAfterSalePaymentFeignDetailVO>> ordersPayMap=null;
        //是否为合同订单
        boolean isContractOrder = ParamVerifyUtils.isContractOrderType(saveVO.getOrderType());
        List<Long> orderIds = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getOrderId).distinct().collect(Collectors.toList());
        if(!isContractOrder){
            //查询订单支付记录
            ordersPayMap = getOrdersPayList(orderIds);
        }
        // 验证退款参数
        for (ReturnGoodsDetailSaveVO item : saveVO.getReturnGoodsList()) {
            // 退货数量不能大于采购数量
            if (item.getReturnCount() > item.getPurchaseCount()) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_RETURN_COUNT_ERROR);
            }
            if(item.getContractId()!=null&&item.getContractId()==0){
                item.setContractId(null);
            }
            // 验证合同流程，合同参数
            if (isContractOrder) {
                if (item.getContractId() == null|| !StringUtils.hasLength(item.getContractNo())) {
                    throw new BusinessException(ResponseCode.AS_RETURN_GOODS_CONTRACT_INFO_ERROR);
                }
            }else{
                List<OrderAfterSalePaymentFeignDetailVO> payList = ordersPayMap.get(item.getOrderId());
                if (CollectionUtil.isEmpty(payList)) {
                    continue;
                }
                // 循环验证支付信息
                for (OrderAfterSalePaymentFeignDetailVO paySaveVO : payList) {
                    // 待确认支付结果的订单不允许售后退货
                    if (paySaveVO.getConfirmPayment()) {
                        throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PAY_STATUS_ERROR);
                    }
                }
            }
        }
/*        //校验售后工作流是否可用
        if (isContractOrder) {
            List<Long> contractIds = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getContractId).distinct().collect(Collectors.toList());
            //验证合同采购工作流是否有效
            feignService.checkPurchaseProcess(user.getMemberId(), user.getMemberRoleId(), OrderPurchaseProcessTypeEnum.AFTER_SALES_RETURNS, contractIds);
        }else {
            List<Long> skuIds = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getSkuId).distinct().collect(Collectors.toList());
            Long shopId = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getShopId).findFirst().orElse(null);
            //验证交易工作流是否有效
            feignService.checkTradeProcess(user.getMemberId(), user.getMemberRoleId(), OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS, skuIds, shopId);
        }*/
        //查询订单商品项
        List<OrderAfterSaleProductFeignDetailVO> orderProductRecordList = getOrderProductRecordList(saveVO.getReturnGoodsList());
        // 采购会员、供应商，选中订单校验
        //checkPurchaseAndSupplyByOrderIds(user, saveVO);
        //验证工作流
        List<OrderProductUpdateFeignVO> updateOrderList = new ArrayList<>();
        ReturnGoodsDO returnDO;
        // 如果申请id为空或等于0，则表示新增
        boolean isSave=(saveVO.getReturnId() == null || saveVO.getReturnId() <= 0);
        if (isSave) {
            //增加数量校验（可退数量<=采购数量-已申退数量）
            checkReturnGoodsNum(saveVO,1,null,orderProductRecordList);
            // 新增一个申请  组装DO对象
            returnDO = convertAddReturnGoodsDO(user, saveVO);
        }
        // 更新
        else {

            // 如果当前申请是不接受申请，则删除当前申请，并重新新增一个申请
            ReturnGoodsDO oldReturnDO = returnRepository.findById(saveVO.getReturnId()).orElse(null);
            if (oldReturnDO == null) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
            }
            List<ReturnGoodsDetailDO> goodsDetailDOS = returnGoodsDetailRepository.findByReturnId(oldReturnDO.getId());
            //增加数量校验（可退数量<=采购数量-已申退数量）
            checkReturnGoodsNum(saveVO,2,goodsDetailDOS,orderProductRecordList);

            // 如果上次申请为不接受申请，此时删除该申请再新增一个新申请（不接受申请时，已还原的商品数量）
            if (oldReturnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode())) {
                // 把旧申请删除
                returnRepository.deleteById(oldReturnDO.getId());
                // 删除历史退货商品
                returnGoodsDetailRepository.deleteAllByReturnId(oldReturnDO.getId());
                // 删除历史退款记录
                returnGoodsRefundDetailRepository.deleteAllByReturnId(oldReturnDO.getId());

                // 新增一个申请  组装DO对象
                returnDO = convertAddReturnGoodsDO(user, saveVO);
            } else {
                // 记录需要还原的商品数量
                goodsDetailDOS.forEach(r -> {
                    OrderProductUpdateFeignVO entity = new OrderProductUpdateFeignVO();
                    entity.setId(r.getOrderRecordId());
                    entity.setOrderId(r.getOrderId());
                    entity.setReturnCount(-r.getReturnCount());
                    double refundAmount=0D;
                    if(CollectionUtil.isNotEmpty(r.getRefundList())){
                        refundAmount=-r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).sum();
                    }
                    entity.setRefundAmount(refundAmount);
                    updateOrderList.add(entity);
                });
                returnDO = oldReturnDO;
                // 非待提交状态不允许修改数据
                if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
                    throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_UPDATE);
                }

                returnDO.setProofFileList(saveVO.getProofFileList());
                returnDO.setApplyAbstract(saveVO.getApplyAbstract());
                returnDO.setReturnGoodsAddress(saveVO.getReturnGoodsAddress());
                returnDO.setUpdateTime(System.currentTimeMillis());
                returnDO.setReturnReason(saveVO.getReturnReason());
                returnDO.setShopId(saveVO.getShopId());
                returnDO.setShopLogo(saveVO.getShopLogo());
                returnDO.setShopName(saveVO.getShopName());
            }
        }


        returnRepository.saveAndFlush(returnDO);
        returnDO.setApplyNo(CodeUtils.digits32(Constants.AFTER_SALE_RETURN_PREFIX, returnDO.getId(), Constants.AFTER_SALE_ORDER_NO_MAX_LENGTH));
        //returnRepository.saveAndFlush(returnDO);

        // 删除历史退货商品
        returnGoodsDetailRepository.deleteAllByReturnId(returnDO.getId());
        // 删除历史退货物料
        returnGoodsDetailMaterielRepository.deleteAllByReturnId(returnDO.getId());
        // 删除历史退款记录
        returnGoodsRefundDetailRepository.deleteAllByReturnId(returnDO.getId());
        // 组装现有退货商品
        List<ReturnGoodsDetailDO> returnGoodsDetailDOList = convertAddReturnedGoodsDO(isContractOrder,returnDO.getId(), saveVO.getReturnGoodsList(),orderProductRecordList,ordersPayMap);

        // 赋值退款金额
        Double refundAmount = returnGoodsDetailDOList.stream()
                .mapToDouble(o -> null == o.getRefundList() ?
                        0 : o.getRefundList().stream()
                        .mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount)
                        .sum())
                .sum();
        returnDO.setRefundAmount(refundAmount);
        //合同订单
        if(isContractOrder){
            Map<Long, OrderAfterSaleProductFeignDetailVO> orderProductMap = orderProductRecordList.stream().collect(Collectors.toMap(OrderAfterSaleProductFeignDetailVO::getOrderProductId, o -> o, (o1, o2) -> o1));
            double totalRefundAmount = saveVO.getReturnGoodsList().stream().mapToDouble(o -> {
                OrderAfterSaleProductFeignDetailVO detailVO = orderProductMap.get(o.getOrderRecordId());
                BigDecimal amount=BigDecimal.ZERO;
                if(detailVO!=null){
                    amount= NumberUtil.mul(detailVO.getRefPrice(), detailVO.getQuantity());
                }
                return amount.doubleValue();
            }).sum();
            returnDO.setRefundAmount(totalRefundAmount);
        }
        // 记录需要更新的商品数量
        returnGoodsDetailDOList.
                forEach(r -> {
                    OrderProductUpdateFeignVO entity = new OrderProductUpdateFeignVO();
                    entity.setId(r.getOrderRecordId());
                    entity.setOrderId(r.getOrderId());
                    // 同一订单商品合并为一条
                    OrderProductUpdateFeignVO oldEntity = updateOrderList.stream().filter(o -> o.getId().equals(r.getOrderRecordId())).findFirst().orElse(null);
                    if (oldEntity != null) {
                        oldEntity.setReturnCount(oldEntity.getReturnCount() + r.getReturnCount());
                        if(CollectionUtil.isNotEmpty(r.getRefundList())) {
                            oldEntity.setRefundAmount(oldEntity.getRefundAmount() + r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).sum());
                        }else{
                            oldEntity.setRefundAmount(oldEntity.getRefundAmount());
                        }
                    } else {
                        entity.setRefundAmount(null == r.getRefundList() ? 0 : r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).sum());
                        entity.setReturnCount(r.getReturnCount());
                        updateOrderList.add(entity);
                    }
                });

        // 保存退货商品
        returnGoodsDetailRepository.saveAll(returnGoodsDetailDOList);
        //保存退货关联商品
        if(isContractOrder){
            List<ReturnGoodsDetailAssociatedDO> materielDOS = returnGoodsDetailDOList.stream().map(o -> {
                ReturnGoodsDetailAssociatedDO materielDO = o.getAssociatedDO();
                materielDO.setReturnDetailId(o.getId());
                return materielDO;
            }).collect(Collectors.toList());
            returnGoodsDetailMaterielRepository.saveAll(materielDOS);
        }
        // 开启内部工作流
        SimpleTaskCompleteVO simpleTaskCompleteVO = processFeignService.startSimpleProcess(returnDO.getMemberId(), returnDO.getRoleId(), returnDO.getInnerTaskType(), returnDO.getId());

        returnDO.setInnerTaskId(simpleTaskCompleteVO.getTaskId());
        returnDO.setInnerTaskStep(simpleTaskCompleteVO.getStep());
        returnDO.setInnerStatus(simpleTaskCompleteVO.getStatus());
        // 开启外部工作流
        SimpleTaskCompleteVO simpleTaskCompleteVOOut = processFeignService.startSimpleProcess(returnDO.getMemberId(), returnDO.getRoleId(), returnDO.getOuterTaskType(), returnDO.getId());
        returnDO.setOuterTaskId(simpleTaskCompleteVOOut.getTaskId());
        returnDO.setOuterTaskStep(simpleTaskCompleteVOOut.getStep());
        returnDO.setOuterStatus(simpleTaskCompleteVOOut.getStatus());

        returnDO.setApplyTime(System.currentTimeMillis());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        if (saveVO.getReturnId() == null || saveVO.getReturnId() <= 0) {

            // 售后退货申请待提交退货申请单+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            SystemMessageRequest request = new SystemMessageRequest();
            request.setMemberId(returnDO.getMemberId());
            request.setRoleId(returnDO.getRoleId());
            request.setMessageNotice(MessageTemplateCode.return_goods_apply);
            List<String> params = new ArrayList<>();
            params.add(returnDO.getApplyNo());
            params.add(returnDO.getApplyAbstract());
            request.setParams(params);
            feignService.sendSystemMessage(request);
        }

        // 更新售后商品数量
        List<OrderProductUpdateFeignVO> updateOrderListTemp = updateOrderList.stream().filter(o -> o.getReturnCount() != 0).collect(Collectors.toList());
        if (updateOrderListTemp.size() > 0) {
            List<OrderAfterSaleVO> orderAfterSaleVOS = buildUpdateOrderParamBySave(updateOrderListTemp);
            Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(orderAfterSaleVOS);
            if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.AS_UPDATE_RETURN_GOODS_COUNT_ERROR);
            }
        }

        return Wrapper.success(returnDO.getId());
    }

//    /**
//     * 校验售后退货申请，填写的采购会员、供应会员，和选中的订单信息是否符合
//     * @param user 采购会员信息
//     * @param saveVO 售后退货信息
//     */
//    private void checkPurchaseAndSupplyByOrderIds(UserLoginCacheDTO user, ReturnGoodsSaveVO saveVO) {
//        // 1.构建【远端调用-订单服务-订单会员信息校验接口】请求参数
//        CheckOrderMemberAfterSaleVO request = new CheckOrderMemberAfterSaleVO();
//        request.setBuyerMemberId(user.getMemberId());
//        request.setBuyerRoleId(user.getMemberRoleId());
//        request.setVendorMemberId(saveVO.getSupplierMemberId());
//        request.setVendorRoleId(saveVO.getSupplierRoleId());
//        List<Long> orderIds = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getOrderId).distinct().collect(Collectors.toList());
//        request.setOrderIds(orderIds);
//        // 2.远端调用服务
//        Wrapper<Boolean> wrapper = feignService.checkAfterSaleOrderMember(request);
//        if (Optional.ofNullable(wrapper)
//                .map(res ->
//                        res.getCode() != ResponseCode.SUCCESS.getCode() // 不成功
//                                || res.getData()) // 校验失败
//                .orElse(true)) {
//            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_MEMBER_INFO);
//        }
//    }

    /**
     * 组装新增退货DO
     * @author 伍将
     * @date 2020/9/9
     */
    private ReturnGoodsDO convertAddReturnGoodsDO(UserLoginCacheDTO user, ReturnGoodsSaveVO saveVO) {

        Long parentMemberId = saveVO.getSupplierMemberId();
        Long parentMemberRoleId = saveVO.getSupplierRoleId();
        Integer innerTaskType = ProcessEnum.AFTER_SALE_RETURN_GOODS_INNER_VERIFY.getCode();

        ReturnGoodsDO returnDO = new ReturnGoodsDO();
        returnDO.setApplyNo("-");//这里写死，保存后再去标识id生成编号
        returnDO.setMemberId(user.getMemberId());
        returnDO.setRoleId(user.getMemberRoleId());
        returnDO.setParentMemberId(parentMemberId);
        returnDO.setParentMemberRoleId(parentMemberRoleId);
        returnDO.setConsumerName(user.getCompany());
        returnDO.setSupplierName(saveVO.getSupplierMemberName());
        returnDO.setApplyAbstract(saveVO.getApplyAbstract());
        returnDO.setReturnGoodsAddress(saveVO.getReturnGoodsAddress());
        returnDO.setProofFileList(saveVO.getProofFileList());
        returnDO.setApplyTime(System.currentTimeMillis());
        returnDO.setRefunded(0D);
        returnDO.setInnerTaskType(innerTaskType);
        returnDO.setOuterTaskType(saveVO.getTaskType());
        returnDO.setCreateTime(System.currentTimeMillis());
        returnDO.setUpdateTime(0L);
        returnDO.setOrderType(saveVO.getOrderType());
        returnDO.setReturnReason(saveVO.getReturnReason());
        returnDO.setShopId(saveVO.getShopId());
        returnDO.setShopLogo(saveVO.getShopLogo());
        returnDO.setShopName(saveVO.getShopName());
         // 设置是否需要发票
        returnDO.setNeedInvoice(CommonBooleanEnum.NO.getCode());
       List<String> orderNoList = saveVO.getReturnGoodsList().stream().map(ReturnGoodsDetailSaveVO::getOrderNo).distinct().collect(Collectors.toList());
        for (String orderNO : orderNoList) {
            Wrapper<OrderSettleAccountInvoiceFeignDetailVO> wrapper = feignService.findSettleAccountInvoiceDetail(orderNO);
            if (null != wrapper && ResponseCode.SUCCESS.getCode() == wrapper.getCode()
                    && null != wrapper.getData() && null != wrapper.getData().getInvoiceId()) {
                returnDO.setNeedInvoice(CommonBooleanEnum.YES.getCode());
                break;
            }
        }
        // 设置代客标识
        returnDO.setAgentFlag(Optional.ofNullable(saveVO.getAgentFlag()).orElse(AgentFlagEnum.NOT.getCode()));
        return returnDO;
    }

    //验证退货物料信息
//    private void checkMaterielDO(ReturnGoodsDetailAssociatedDO materielDO){
//        if(materielDO==null){return;}
//        if(!StringUtils.hasLength(materielDO.getProductId())){
//            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_MATERIEL_REQUIRED);
//        }else if(!StringUtils.hasLength(materielDO.getProductName())){
//            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_MATERIEL_REQUIRED);
//        }
//    }

    /**
     * 组装新增退货商品DO（不验证参数）
     * @author 伍将
     * @date 2020/9/9
     * @param returnId:
     * @param goodsList:
     * @return : java.util.List<com.ssy.lingxi.after.sale.entity.ReturnedGoodsDO>
     **/
    private List<ReturnGoodsDetailDO> convertAddReturnedGoodsDO(boolean isContractOrder,Long returnId, List<ReturnGoodsDetailSaveVO> goodsList,List<OrderAfterSaleProductFeignDetailVO> orderProductRecordList,Map<Long, List<OrderAfterSalePaymentFeignDetailVO>> ordersPayMap) {

        Map<Long, OrderAfterSaleProductFeignDetailVO> orderProductMap = orderProductRecordList.stream().collect(Collectors.toMap(OrderAfterSaleProductFeignDetailVO::getOrderProductId, o -> o, (o1, o2) -> o1));
        return goodsList.stream().map(r -> {
            ReturnGoodsDetailDO addDo = new ReturnGoodsDetailDO();
            addDo.setReturnId(returnId);
            addDo.setOrderId(r.getOrderId());
            addDo.setShopId(r.getShopId());
            addDo.setOrderNo(r.getOrderNo());
            addDo.setOrderRecordId(r.getOrderRecordId());
            addDo.setProductId(r.getProductId());
            addDo.setProductName(r.getProductName());
            addDo.setCategory(r.getCategory());
            addDo.setBrand(r.getBrand());
            addDo.setUnit(r.getUnit());
            addDo.setSkuId(r.getSkuId());
            addDo.setSkuPic(r.getSkuPic());
            OrderAfterSaleProductFeignDetailVO orderProduct = orderProductMap.get(r.getOrderRecordId());
            if(orderProduct==null){
                throw new BusinessException(ResponseCode.AS_RETURN_PRODUCT_IS_NOT_EXISTS);
            }
            addDo.setPurchasePrice(orderProduct.getRefPrice().doubleValue());
            addDo.setPurchaseCount(orderProduct.getQuantity().doubleValue());
            // 支付金额等于实际支付金额
            addDo.setPayAmount(orderProduct.getPaidAmount().doubleValue());
            addDo.setReturnCount(r.getReturnCount());
            addDo.setDeliveryCount(0D);
            addDo.setReceiveCount(0D);
            addDo.setStorageCount(0D);
            addDo.setReturnReason(r.getReturnReason());
            addDo.setIsNeedReturn(CommonBooleanEnum.YES.getCode()); //新增时，默认需要退货
            addDo.setIsHasTax(r.getIsHasTax());
            addDo.setTaxRate(r.getTaxRate());
            addDo.setContractId(r.getContractId());
            addDo.setContractNo(r.getContractNo());
            addDo.setType(r.getType());
            //物料信息
            if(isContractOrder){
                ReturnGoodsDetailAssociatedDO materielDO=new ReturnGoodsDetailAssociatedDO();
                materielDO.setProductId(r.getAssociatedProductId());
                materielDO.setProductName(r.getAssociatedProductName());
                materielDO.setCategory(r.getAssociatedCategory());
                materielDO.setBrand(r.getAssociatedBrand());
                materielDO.setUnit(r.getAssociatedUnit());
                materielDO.setType(r.getAssociatedType());
                materielDO.setReturnId(returnId);
                //验证退货物料信息
                /*非强关联，可以不[关联报价商品],不再校验 checkMaterielDO(materielDO);*/
                addDo.setAssociatedDO(materielDO);
            }
            //支付记录
            if(ordersPayMap!=null) {
                List<OrderAfterSalePaymentFeignDetailVO> voList = ordersPayMap.get(r.getOrderId());
                //组装退款明细
                if (null != voList && voList.size() > 0) {
                    Set<ReturnGoodsRefundDetailDO> refundList = new HashSet<>();
                    voList.forEach(pay -> {
                        ReturnGoodsRefundDetailDO refundDO = new ReturnGoodsRefundDetailDO();
                        refundDO.setOrderId(r.getOrderId());
                        refundDO.setOrderNo(r.getOrderNo());
                        refundDO.setPayId(pay.getPaymentId());
                        refundDO.setExternalState(3);
                        refundDO.setPayCount(pay.getBatchNo());
                        refundDO.setPayNode(pay.getPayNode());
                        refundDO.setPayRatio(pay.getPayRate().doubleValue());
                        refundDO.setPayAmount(pay.getPayAmount().doubleValue());
                        refundDO.setPayWay(pay.getPayType());
                        refundDO.setChannel(pay.getPayChannel().longValue());
                        // 支付状态为确认到账时，计算退款金额
                        // 系统取订单详情中外部状态为确认到账的支付信息，自动按照退货数量计算退款金额，退款金额=退货数量*单价*支付比例，保留小数点后两位
                        double refundAmount = NumberUtil.mul(NumberUtil.mul(r.getReturnCount(), r.getPurchasePrice()), pay.getPayRate().doubleValue());
                        //四舍五入保留2位
                        refundAmount=new BigDecimal(refundAmount).setScale(2, RoundingMode.HALF_UP).doubleValue();
                        if (pay.getAccomplished()) {
                            refundDO.setRefundAmount(refundAmount);
                            refundDO.setTobeRefundAmount(0D);
                            refundDO.setPayTime(com.ssy.lingxi.common.utils.DateUtil.convertToTimeMillis(pay.getPayTime()));
                            refundDO.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.TO_BE_REFUND.getCode());
                            refundDO.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.TO_BE_REFUND.getCode());
                        } else {
                            refundDO.setRefundAmount(0D);
                            refundDO.setTobeRefundAmount(refundAmount);
                            refundDO.setPayTime(0L);
                            refundDO.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.UN_NEED_REFUND.getCode());
                            refundDO.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.UN_NEED_REFUND.getCode());
                        }
                        refundDO.setCreateTime(System.currentTimeMillis());
                        refundDO.setPayRuleId(pay.getFundMode().longValue());
                        refundDO.setTransactionPayId(pay.getTradeNo());
                        refundDO.setReturnId(returnId);
                        refundDO.setReturnGoods(addDo);
                        refundList.add(refundDO);
                    });

                    addDo.setRefundList(refundList);
                }
            }

            return addDo;
        }).collect(Collectors.toList());
    }

    private List<OrderAfterSaleVO> buildUpdateOrderParamBySave(List<OrderProductUpdateFeignVO> orderProducts){
        Map<Long, List<OrderProductAfterSaleVO>> orderProductMap=new HashMap<>();
        orderProducts.forEach(r ->{
            List<OrderProductAfterSaleVO> orderProductList = orderProductMap.get(r.getOrderId());
            if(CollectionUtil.isEmpty(orderProductList)){
                orderProductList=new ArrayList<>();
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setReturnCount(BigDecimal.valueOf(r.getReturnCount()));
                vo.setReturnAmount(BigDecimal.valueOf(r.getRefundAmount()));
                vo.setProductId(r.getId());
                orderProductList.add(vo);
                orderProductMap.put(r.getOrderId(),orderProductList);
            }else{
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setReturnCount(BigDecimal.valueOf(r.getReturnCount()));
                vo.setReturnAmount(BigDecimal.valueOf(r.getRefundAmount()));
                vo.setProductId(r.getId());
                orderProductList.add(vo);
            }
        });
        return convertOrderProductMapToList(orderProductMap);
    }

    private List<OrderAfterSaleVO> convertOrderProductMapToList(Map<Long, List<OrderProductAfterSaleVO>> orderProductMap){
        // 更新售后商品数量
        List<OrderAfterSaleVO> afterSales=new ArrayList<>();
        orderProductMap.forEach((k,v)->{
            OrderAfterSaleVO orderVO=new OrderAfterSaleVO();
            orderVO.setOrderId(k);
            orderVO.setProducts(v);
            afterSales.add(orderVO);
        });
        return afterSales;
    }

    /**
     * 构建
     * @param returnId 退货单id
     * @return 构建售后服务 - 修改订单商品的换货、退货、维修数量、退款金额列表
     */
    private List<OrderAfterSaleVO> buildUpdateOrderParamBySave(Long returnId){
        List<ReturnGoodsDetailDO> goodsDetailDOS = returnGoodsDetailRepository.findByReturnId(returnId);
        Map<Long, List<OrderProductAfterSaleVO>> orderProductMap=new HashMap<>();
        goodsDetailDOS.forEach(r ->{
            List<OrderProductAfterSaleVO> orderProductList = orderProductMap.get(r.getOrderId());
            double returnCount =  -r.getReturnCount();
            double amount = -r.getRefundList().stream().mapToDouble(ReturnGoodsRefundDetailDO::getRefundAmount).sum();
            if(CollectionUtil.isEmpty(orderProductList)){
                orderProductList=new ArrayList<>();
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setReturnCount(BigDecimal.valueOf(returnCount));
                vo.setReturnAmount(BigDecimal.valueOf(amount));
                vo.setProductId(r.getOrderRecordId());
                orderProductList.add(vo);
                orderProductMap.put(r.getOrderId(),orderProductList);
            }else{
                OrderProductAfterSaleVO vo=new OrderProductAfterSaleVO();
                vo.setReturnCount(BigDecimal.valueOf(returnCount));
                vo.setReturnAmount(BigDecimal.valueOf(amount));
                vo.setProductId(r.getOrderRecordId());
                orderProductList.add(vo);
            }
        });
        return convertOrderProductMapToList(orderProductMap);
    }

    /**
     * 删除退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user:
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> delete(UserLoginCacheDTO user, Long returnId) {

        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 待提交状态且从未提交过的申请单的可以删除
        if (!returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode())
                || !returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELETE);
        }

        returnRepository.deleteById(returnDO.getId());

        List<OrderAfterSaleVO> afterSales= buildUpdateOrderParamBySave(returnDO.getId());
        Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(afterSales);
        if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_UPDATE_RETURN_GOODS_COUNT_ERROR);
        }

        // 售后退货申请待提交退货申请单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        return Wrapper.success();
    }

    /**
     * 提交退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user:
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> submit(UserLoginCacheDTO user, Long returnId) {

        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_SUBMIT);
        }

        //boolean contractOrderType = ParamVerifyUtils.isContractOrderType(returnDO.getOrderType());
        // 非合同流程的退货单，查询退款金额，并验证
/*保存时已更新订单金额与数量        if (!contractOrderType&&!ProcessEnum.AFTER_SALE_RETURN_GOODS_CONTRACT_VERIFY.getCode().equals(returnDO.getOuterTaskType())
                && !ProcessEnum.AFTER_SALE_RETURN_GOODS_CONTRACT_MANUAL_DELIVERY.getCode().equals(returnDO.getOuterTaskType())) {
            List<ReturnGoodsDetailDO> detailList = returnGoodsDetailRepository.findByReturnId(returnId);
            Wrapper<?> updateOrderWrapper = feignService.updateOrderPayPrice(detailList, false);
            if (null == updateOrderWrapper || ResponseCode.SUCCESS.getCode() != updateOrderWrapper.getCode()) {
                throw new BusinessException(ResponseCode.AS_RETURN_UPDATE_ORDER_PAY_ERROR);
            }
        }*/

        // 申请的提交到外部
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        // 设置内部状态为待提交
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode());
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnId, returnDO.getOuterStatus(), RepairGoodsOuterStatusEnum.TO_BE_CONFIRM.getMessage(), ReturnGoodsActionEnum.SUBMIT.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, returnId, returnDO.getInnerStatus(), ReplaceGoodsHelpEnum.SUBMIT.getMessage(), ReturnGoodsActionEnum.SUBMIT.getMessage(), "");

        // 售后退货申请待提交-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理待提交审核换货申请单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_wait_audit);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 供应商分页查询退货申请
     * @author 伍将
     * @date 2020/9/4
     * @param user: 
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageBySupplier(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(pageVO.getInnerStatus());
        returnGoodsPageVO.setOuterStatus(pageVO.getOuterStatus());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 供应商获取退货申请详情
     * @author 伍将
     * @date 2020/9/4
     * @param user: 
     * @param returnId: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsApplyDetailVO>
     **/
    @Override
    public Wrapper<ReturnGoodsDetailVO> getDetailBySupplier(UserLoginCacheDTO user, Long returnId) {
        return getDetail(user, returnId, true);
    }

    /**
     * 供应商分页查询待提交退货
     * @author 伍将
     * @date 2020/9/11
     * @param user: 
     * @param pageVO: 
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeSubmitBySupplier(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 提交审核
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> submitVerify(UserLoginCacheDTO user, ReturnSubmitVerifyVO verifyVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为待提交时才允许提交审核
        if (!ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(returnDO.getOuterStatus())
                || !ReturnGoodsInnerStatusEnum.TO_BE_SUBMIT.getCode().equals(returnDO.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 更新退货地址
        if (returnDO.getReturnGoodsAddress() == null) {
            returnDO.setReturnGoodsAddress(new ReceiveGoodsBO());
        }
        returnDO.getReturnGoodsAddress().setReceiveId(verifyVO.getReceiveId());
        returnDO.getReturnGoodsAddress().setReceiveAddress(verifyVO.getReceiveAddress());
        returnDO.getReturnGoodsAddress().setReceiveUserName(verifyVO.getReceiveUserName());
        returnDO.getReturnGoodsAddress().setReceiveUserTel(verifyVO.getReceiveUserTel());

        // 执行内部流转
        completeInnerTask(returnDO, verifyVO.getIsPass());
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商内部流转记录
        String statusName = ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus());
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), statusName, ReturnGoodsActionEnum.INNER_SUBMIT_VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后退货处理待提交审核退货申请单-1,待审核退货申请单（一级）/待确认退货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReturnHandleOperateTypeEnum operateTypeEnum = AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_STEP1;
        if (ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(returnDO.getInnerStatus())) {
            operateTypeEnum = AfterSaleReturnHandleOperateTypeEnum.TO_BE_CONFIRM;
        }
        noticeVO.setIncreaseOperateType(operateTypeEnum.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        String messageTemplateCode = MessageTemplateCode.return_goods_handle_audit_step_1;
        if (ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(returnDO.getInnerStatus())) {
            messageTemplateCode = MessageTemplateCode.return_goods_handle_confirm;
        }
        request.setMessageNotice(messageTemplateCode);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 新增内部工作流记录
     * @author 伍将
     * @date 2020/9/11
     * @param user :
     * @param repairId :
     * @param statusCode :
     * @param statusName :
     * @param operate :
     * @param opinion :
     **/
    private void addInnerWorkflowRecord(UserLoginCacheDTO user, Long repairId, Integer statusCode, String statusName, String operate, String opinion) {

        InnerWorkflowRecordDO recordDO = new InnerWorkflowRecordDO();
        recordDO.setAfterSaleId(repairId);
        recordDO.setAfterSaleType(AfterSaleTypeEnum.RETURN.getCode());
        recordDO.setUserId(user.getUserId());
        recordDO.setMemberId(user.getMemberId());
        recordDO.setRoleId(user.getMemberRoleId());
        recordDO.setOperator(user.getUserName());
        recordDO.setDepartment(user.getUserOrgName());
        recordDO.setJobTitle(user.getUserJobTitle());
        recordDO.setStatus(ReturnGoodsInnerStatusEnum.getMessage(statusCode));
        recordDO.setStatusCode(statusCode);
        recordDO.setOperate(operate);
        recordDO.setOperateTime(System.currentTimeMillis());
        recordDO.setOpinion(opinion);

        innerWorkflowRecordRepository.saveAndFlush(recordDO);

    }

    /**
     * 新增外部工作流记录
     * @author 伍将
     * @date 2020/9/11
     * @param user :
     * @param repairId :
     * @param statusCode :
     * @param statusName :
     * @param operate :
     * @param opinion :
     **/
    private void addOuterWorkflowRecord(UserLoginCacheDTO user, Long repairId, Integer statusCode, String statusName, String operate, String opinion) {

        OuterWorkflowRecordDO recordDO = new OuterWorkflowRecordDO();
        recordDO.setAfterSaleId(repairId);
        recordDO.setAfterSaleType(AfterSaleTypeEnum.RETURN.getCode());
        recordDO.setUserId(user.getUserId());
        recordDO.setMemberId(user.getMemberId());
        recordDO.setRoleId(user.getMemberRoleId());
        recordDO.setRoleName(user.getMemberRoleName());
        recordDO.setStatus(ReturnGoodsOuterStatusEnum.getMessage(statusCode));
        recordDO.setStatusCode(statusCode);
        recordDO.setOperate(operate);
        recordDO.setOperateTime(System.currentTimeMillis());
        recordDO.setOpinion(opinion);

        outerWorkflowRecordRepository.saveAndFlush(recordDO);

    }

    /**
     * 供应商分页查询待审核一级退货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeVerifyStepOne(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 一级审核
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepOne(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为提交审核申请单才允许一级审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_PASSED.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 执行内部流转
        completeInnerTask(returnDO, verifyVO.getIsPass());
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商内部流转记录
        String statusName = ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus());
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), statusName, ReturnGoodsActionEnum.INNER_VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后退货处理待审核退货申请单（一级）-1,待审核退货申请单（二级）/待确认退货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_STEP1.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReturnHandleOperateTypeEnum operateTypeEnum = AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_STEP2;
        if (ReturnGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode().equals(returnDO.getInnerStatus())) {
            operateTypeEnum = AfterSaleReturnHandleOperateTypeEnum.TO_BE_CONFIRM;
        }
        noticeVO.setIncreaseOperateType(operateTypeEnum.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        String messageTemplateCode = MessageTemplateCode.return_goods_handle_audit_step_2;
        if (ReturnGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode().equals(returnDO.getInnerStatus())) {
            messageTemplateCode = MessageTemplateCode.return_goods_handle_confirm;
        }
        request.setMessageNotice(messageTemplateCode);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 供应商分页查询待审核二级退货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeVerifyStepTwo(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.VERIFY_STEP1_PASSED.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 二级审核
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepTwo(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为一级审核通过才允许二级审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.VERIFY_STEP1_PASSED.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 执行内部流转
        completeInnerTask(returnDO, verifyVO.getIsPass());
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商内部流转记录
        String statusName = ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus());
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), statusName, ReturnGoodsActionEnum.INNER_VALIFY.getMessage(), verifyVO.getOpinion());

        // 售后退货处理待审核退货申请单（二级）-1,待确认退货申请单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_STEP2.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_confirm);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 供应商分页查询等待确认审核的退货
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeConfirmVerify(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));

            // 查询外部状态为待提交或不接受申请的
            List<Integer> innerStatusList = new ArrayList<>();
            innerStatusList.add(ReturnGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode());
            innerStatusList.add(ReturnGoodsInnerStatusEnum.VERIFY_STEP2_UN_PASSED.getCode());
            innerStatusList.add(ReturnGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode());
            innerStatusList.add(ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode());
            list.add(criteriaBuilder.in(root.get("innerStatus")).value(innerStatusList));

            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), true);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 退货-更新营销活动商品的销量缓存
     * @param returnId 退货单id
     */
    private void updateMarketingActivityGoodsSales(Long returnId,String refundNo,UserLoginCacheDTO user,Long orderTime){
        List<ReturnGoodsDetailDO> returnGoodsDetailDOList = returnGoodsDetailRepository.findByReturnId(returnId);
        List<GoodsSalesItemReq> itemList=new ArrayList<>();
        for (ReturnGoodsDetailDO returnDetail :returnGoodsDetailDOList){
            String orderKey= MkRedisKeyConstants.getOrderSkuJoinActivitiesKey(returnDetail.getOrderNo());
            GoodsSalesItemReq itemReq=new GoodsSalesItemReq();
            itemReq.setOrderNo(refundNo);
            itemReq.setOrderId(returnId);
            itemReq.setOriginOrderNo(returnDetail.getOrderNo());
            itemReq.setSkuId(returnDetail.getSkuId());
            itemReq.setNum(-returnDetail.getReturnCount());
            Set<ReturnGoodsRefundDetailDO> refundSet = returnDetail.getRefundList();
            if(CollectionUtil.isNotEmpty(refundSet)){
                double sum = refundSet.stream().mapToDouble(o -> com.ssy.lingxi.after.sale.utils.NumberUtil.setZeroOfNull(o.getRefundAmount())).sum();
                itemReq.setAmount(-sum);
            }
            itemList.add(itemReq);
        }
        GoodsSalesReq goodsSalesReq=new GoodsSalesReq();
        goodsSalesReq.setRecordType(ActivityRecordTypeEnum.REFUND.getCode());
        goodsSalesReq.setMemberId(user.getMemberId());
        goodsSalesReq.setMemberName(user.getCompany());
        goodsSalesReq.setRoleId(user.getMemberRoleId());
        goodsSalesReq.setItemList(itemList);
        goodsSalesReq.setOrderTime(orderTime);
        feignService.updateActivitySkuSales(goodsSalesReq);
    }

    /**
     * 确认审核
     * @author 伍将
     * @date 2020/9/11
     * @param user:
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmVerify(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认，内部状态为二级审核通过/二级审核不通过/一级审核不通过/提交审核不通过时才允许确认审核
        if (!ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(returnDO.getOuterStatus())
                || (!ReturnGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.VERIFY_STEP2_UN_PASSED.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.VERIFY_STEP1_UN_PASSED.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.SUBMIT_VERIFY_UN_PASSED.getCode().equals(returnDO.getInnerStatus()))
        ) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }
        // 当选择审核不通过时，审核不通过原因为必填
        if (verifyVO.getIsPass().equals(CommonBooleanEnum.NO.getCode())) {
            if (!StringUtils.hasLength(verifyVO.getOpinion())) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_VERIFY_OPINION_EMPTY);
            }
        }
        // 只有内部状态为二级审核通过的才允许选择接受申请
        if (verifyVO.getIsPass().equals(CommonBooleanEnum.YES.getCode())
                && !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY_ACCEPT);
        }
        // 当内部状态不为二级审核通过时，直接不接受申请
        if (!ReturnGoodsInnerStatusEnum.VERIFY_STEP2_PASSED.getCode().equals(returnDO.getInnerStatus())) {
            verifyVO.setIsPass(CommonBooleanEnum.NO.getCode());
        }

        //非合同订单-还原订单支付金额
        boolean contractOrderType = ParamVerifyUtils.isContractOrderType(returnDO.getOrderType());
        if (CommonBooleanEnum.NO.getCode().equals(verifyVO.getIsPass())&&!contractOrderType) {
            //△供应商驳回退货申请时不还原订单金额与数量，删除时还原
            /*// 不接收申请时，还原订单支付金额
            List<ReturnGoodsDetailDO> detailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
            Wrapper<?> updateOrderWrapper = feignService.updateOrderPayPrice(detailList, true);
            if (null == updateOrderWrapper || ResponseCode.SUCCESS.getCode() != updateOrderWrapper.getCode()) {
                throw new BusinessException(ResponseCode.AS_RETURN_UPDATE_ORDER_PAY_ERROR);
            }*/
        }


        // 执行内部流转
        completeInnerTask(returnDO, verifyVO.getIsPass());

        // 新增供应商内部流转记录
        String statusName = ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus());
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), statusName, ReturnGoodsActionEnum.INNER_CONFIRM.getMessage(), verifyVO.getOpinion());


        //判断是否包含平台审核
        if(ProcessEnum.AFTER_SALE_RETURN_GOODS_PF_MANUAL_DELIVERY.getCode().equals(returnDO.getOuterTaskType())){
        //平台审核
            confirmVerifyByPlatform(user,verifyVO,returnDO);
        }else{
        //常规流程
            confirmVerifyByNormal(user,verifyVO,returnDO);
        }
        return Wrapper.success();
    }

    /**
     * 如果包含平台审核流程
     * @param user 用户
     * @param verifyVO 审核VO
     * @param returnDO 退货表
     */
    private void confirmVerifyByPlatform(UserLoginCacheDTO user,VerifyVO verifyVO,ReturnGoodsDO returnDO){
        Integer oldStatus=returnDO.getOuterStatus();
        returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode());
        // 新增供应商外部流转记录
        String statusName = (verifyVO.getIsPass()==0) ? RepairGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getMessage() : ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getMessage();
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), statusName, ReturnGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

        // 售后退货处理待确认退货申请单-1
        commonReduceOperateNotice(returnDO,oldStatus);

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        //发送通知与增加首页统计计数
        commonSystemMessageAndIncreaseOperateNotice(returnDO,status);

    }

    private void confirmVerifyByNormal(UserLoginCacheDTO user,VerifyVO verifyVO,ReturnGoodsDO returnDO){
        Integer status;
        // 外部流转：确认退货申请单这里直接业务逻辑处理，不进行工作流流转
        if (CommonBooleanEnum.NO.getCode().equals(verifyVO.getIsPass())) {
            returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode());
            //还原退货数量
            List<OrderAfterSaleVO> afterSales= buildUpdateOrderParamBySave(returnDO.getId());
            Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(afterSales);
            if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.AS_UPDATE_RETURN_GOODS_COUNT_ERROR);
            }
        } else {
            returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.ACCEPT_APPLY.getCode());
            //活动订单，feign更新销量数据 售后数量不参与活动统计
            updateMarketingActivityGoodsSales(returnDO.getId(),returnDO.getApplyNo(),user,returnDO.getApplyTime());
        }

        // 新增供应商外部流转记录
        String statusName = ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode().equals(returnDO.getOuterStatus()) ? ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getMessage() :ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getMessage();
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), statusName, ReturnGoodsActionEnum.CONFIRM.getMessage(), verifyVO.getOpinion());

        // 售后退货处理待确认退货申请单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 确认完退货申请后，且外部状态为接受申请时，进入下一步流转环节
        if (returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.ACCEPT_APPLY.getCode())) {

            // 如果外部流程为合同流程，则通知合同执行情况
            if (ProcessEnum.AFTER_SALE_RETURN_GOODS_CONTRACT_VERIFY.getCode().equals(returnDO.getOuterTaskType())
                    || ProcessEnum.AFTER_SALE_RETURN_GOODS_CONTRACT_MANUAL_DELIVERY.getCode().equals(returnDO.getOuterTaskType())) {
                // 查询所有退货商品
                List<ReturnGoodsDetailDO> detailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
                if(detailList.get(0).getContractId()!=null) {
                    List<ContractExecuteInfoAddVO> contractExecuteList = new ArrayList<>();
                    for (ReturnGoodsDetailDO detail : detailList) {
                        ContractExecuteInfoAddVO entity = contractExecuteList.stream().filter(
                                o -> o.getIsHasTax().equals(detail.getIsHasTax()) && o.getTaxRate().equals(detail.getTaxRate()))
                                .findFirst().orElse(null);
                        if (null == entity) {
                            entity = new ContractExecuteInfoAddVO();
                            entity.setContractId(detail.getContractId());
                            entity.setOrderId(returnDO.getId());
                            entity.setOrderNO(returnDO.getApplyNo());
                            entity.setOrderAbstract(returnDO.getApplyAbstract());
                            entity.setOrderType(ContractOrderTypeEnum.RETURN_GOODS.getCode());
                            entity.setOrderTime(returnDO.getApplyTime());
                            // 订单金额=退货数量*采购单价
                            entity.setOrderAmount(NumberUtil.mul(detail.getReturnCount(), detail.getPurchasePrice()));
                            entity.setIsHasTax(detail.getIsHasTax());
                            entity.setTaxRate(detail.getTaxRate());
                            contractExecuteList.add(entity);
                        } else {
                            // 同一税率数据合并，订单金额=现计算订单金额+(退货数量*采购单价)
                            entity.setOrderAmount(entity.getOrderAmount() + (NumberUtil.mul(detail.getReturnCount(), detail.getPurchasePrice())));
                        }
                    }

                    Wrapper<?> contractWrapper = feignService.addContractExecuteInfoList(contractExecuteList);
                    if (null == contractWrapper || ResponseCode.SUCCESS.getCode() != contractWrapper.getCode()) {
                        throw new BusinessException(ResponseCode.AS_UPDATE_CONTRACT_EXECUTE_ERROR);
                    }
                }
            }

            // 检查是否需要退货，如不需要退货，则跳过退货流程
            Boolean isExists = returnGoodsDetailRepository.existsByReturnIdAndIsNeedReturn(returnDO.getId(), CommonBooleanEnum.YES.getCode());
            Integer agree = TaskAgreeEnum.REFUSE.getCode();
            if (isExists) {
                agree = TaskAgreeEnum.AGREE.getCode();
            }else{
                //如果非合同流程
                if(!ProcessUtil.isContractOfReturnGoods(returnDO.getOuterTaskType())){
                    //如果无需退款
                    if(returnDO.getRefundAmount()==0){
                        agree = TaskAgreeEnum.AGREE_CONDITION2.getCode();
                    }
                }
            }
            // 执行外部流转
            completeOuterTask(returnDO, agree);
            status = returnDO.getOuterStatus();

            // 如果外部状态为：待新增退货发货单，则设置内部状态为：待新增退货发货单
            if (ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());

                // 售后退货申请待新增退货发货单+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(returnDO.getMemberId());
                noticeVO.setRoleId(returnDO.getRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(returnDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增待新增退货发货单消息通知
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(returnDO.getMemberId());
                request.setRoleId(returnDO.getRoleId());
                request.setMessageNotice(MessageTemplateCode.return_goods_shipment);
                List<String> params = new ArrayList<>();
                params.add(returnDO.getApplyNo());
                params.add(returnDO.getApplyAbstract());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
            // 如果外部状态为：待退款，则设置内部状态为：待退款
            else if (ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());

                // 售后退货处理(供应商)待退款+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(returnDO.getParentMemberId());
                noticeVO.setRoleId(returnDO.getParentMemberRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(returnDO.getId());
                feignService.addSysOperateNotice(noticeVO);
                // 售后退货处理(平台账户)待退款+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(0L);
                noticeVO.setRoleId(0L);
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(returnDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                List<String> params = new ArrayList<>();
                params.add(returnDO.getApplyNo());
                params.add(returnDO.getApplyAbstract());
                // 新增供应商待退款消息通知
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(returnDO.getParentMemberId());
                request.setRoleId(returnDO.getParentMemberRoleId());
                request.setMessageNotice(MessageTemplateCode.return_goods_handle_refund);
                request.setParams(params);
                feignService.sendSystemMessage(request);
                // 新增平台待退款消息通知
                request = new SystemMessageRequest();
                request.setMemberId(0L);
                request.setRoleId(0L);
                request.setMessageNotice(MessageTemplateCode.return_goods_handle_platform_refund);
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
            // 如果外部状态为：待退货发货,则设置内部状态为:待确认退货发货
            else if (ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());

                // 售后退货申请待退货发货+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(returnDO.getMemberId());
                noticeVO.setRoleId(returnDO.getRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(returnDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增待退货发货消息通知
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(returnDO.getMemberId());
                request.setRoleId(returnDO.getRoleId());
                request.setMessageNotice(MessageTemplateCode.return_goods_return_shipment);
                List<String> params = new ArrayList<>();
                params.add(returnDO.getApplyNo());
                params.add(returnDO.getApplyAbstract());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            } else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(status)){
                //无退款+无退货的->待确认售后完成
                // 待确认售后完成+1
                noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(returnDO.getMemberId());
                noticeVO.setRoleId(returnDO.getRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
                noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
                noticeVO.setIncreaseDataId(returnDO.getId());
                feignService.addSysOperateNotice(noticeVO);

                // 新增待退货发货消息通知
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(returnDO.getMemberId());
                request.setRoleId(returnDO.getRoleId());
                request.setMessageNotice(MessageTemplateCode.return_goods_confirm);
                List<String> params = new ArrayList<>();
                params.add(returnDO.getApplyNo());
                params.add(returnDO.getApplyAbstract());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        }else {
            // 售后退货申请待提交退货申请单+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
        }

        returnRepository.saveAndFlush(returnDO);
    }

    /**
     * 分页查询待退货发货单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeAddReturnDeliveryGoods(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货发货单
     * @author 伍将
     * @date 2020/9/24
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<java.lang.Long>
     **/
    @Transactional
    @Override
    public Wrapper<Long> addReturnDeliveryGoods(UserLoginCacheDTO user,ReturnDeliveryGoodsAddVO addVO) {
        logger.info("tempLog新增退货发货单addReturnDeliveryGoods:addVO:{}", JSONUtil.toJsonStr(addVO));
        ReturnGoodsDO returnDO = returnRepository.findById(addVO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货发货单时，才允许新增发货单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_ADD_DELIVERY_GOODS);
        }
        // 检查发货单商品是否都存在与退货商品中
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        if (returnGoodsDetailList == null || returnGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST);
        }
        Map<Long, ReturnGoodsDetailDO> returnGoodsDetailMap = returnGoodsDetailList.stream().collect(Collectors.toMap(ReturnGoodsDetailDO::getId, v -> v));
        // 检查发货单商品是否匹配退货商品
        ReturnDeliveryGoodsAddProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !returnGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_ERROR);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        returnDeliveryGoodsRepository.deleteByReturnIdAndStatus(addVO.getReturnId(), ReturnDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        Integer returnBatch = returnDeliveryGoodsRepository.countByReturnId(addVO.getReturnId());

        // 新增退货发货单
        ReturnDeliveryGoodsDO deliveryGoodsDO = new ReturnDeliveryGoodsDO();
        deliveryGoodsDO.setBatchNo(returnBatch + 1);
        deliveryGoodsDO.setReturnId(addVO.getReturnId());
        deliveryGoodsDO.setDeliveryOrderNo(CodeUtils.getInvoicesNo("FH"));
        deliveryGoodsDO.setDeliveryTime(addVO.getDeliveryTime());
        deliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        deliveryGoodsDO.setOrderAbstract(addVO.getOrderAbstract());
        deliveryGoodsDO.setRemark(addVO.getRemark());
        deliveryGoodsDO.setInventoryName(addVO.getInventoryName());
        deliveryGoodsDO.setInventoryRole(addVO.getInventoryRole());
        // 新增退货发货单商品
        Set<ReturnDeliveryGoodsDetailDO> detailList = new HashSet<>();
        addVO.getDetailList().forEach(item -> {
            ReturnDeliveryGoodsDetailDO detail = new ReturnDeliveryGoodsDetailDO();
            detail.setOrderNo(item.getOrderNo());
            detail.setDeliveryCount(item.getCount());
            detail.setStorageCount(0.0);
            detail.setProductId(item.getProductId());
            detail.setProductName(item.getProductName());
            detail.setCategory(item.getCategory());
            detail.setBrand(item.getBrand());
            detail.setUnit(item.getUnit());
            // 待退货数量=原始退货数量
            ReturnGoodsDetailDO returnGoodsDetailDO = returnGoodsDetailMap.get(item.getReturnDetailId());
            if (returnGoodsDetailDO != null) {
                detail.setReturnCount(returnGoodsDetailDO.getReturnCount());
            } else {
                detail.setReturnCount(0D);
            }
            detail.setCreateTime(System.currentTimeMillis());
            detail.setUpdateTime(0L);
            detail.setDeliveryGoods(deliveryGoodsDO);
            detail.setReturnGoodsDetailDO(returnGoodsDetailDO);
            detailList.add(detail);
        });
        deliveryGoodsDO.setDetailList(detailList);
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 更新退货申请单
        returnDO.setReturnBatch(returnBatch + 1); // 新的批次号在查出发货单次数上+1
        returnDO.setReturnDeliveryId(deliveryGoodsDO.getId());
        returnDO.setReturnDeliveryNo(deliveryGoodsDO.getDeliveryOrderNo());
        // 新增发货单成功后,内部状态设置为待审核
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_RETURN_SEND_GOODS.getMessage(), ( ReplaceGoodsHelpEnum.SEND_NO.getMessage()+deliveryGoodsDO.getDeliveryOrderNo() ));

        return Wrapper.success(deliveryGoodsDO.getId());
    }

    /**
     * 删除退货发货单
     * @author 伍将
     * @date 2020/9/29
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReturnDeliveryGoods(Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部为待新增退货发货单，内部状态为待审核退货发货单时，才允许删除退货发货单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELETE_DELIVERY_GOODS);
        }

        // 由于发货单存在修改操作，为简便代码逻辑，每次新增或修改发货单，直接删除原始数据再进行新增
        returnDeliveryGoodsRepository.deleteByReturnIdAndStatus(returnId, ReturnDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode());

        // 清空退货发货单号
        returnDO.setReturnDeliveryNo("");
        // 删除发货单成功后,内部状态设置为待新增
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        return Wrapper.success();
    }

    /**
     * 审核退货发货
     * @author 伍将
     * @date 2020/9/24
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> verifyReturnDeliveryGoods(VerifyDeliveryVO verifyVO) {

        // 查询发货单
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findFirstById(verifyVO.getDataId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }

        // 查询退货申请单
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        // 如果发货单id与当前申请单的发货单id不匹配，则无权审核
        if (!deliveryGoodsDO.getId().equals(returnDO.getReturnDeliveryId())) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_ERROR);
        }

        return verifyReturnDeliveryGoodsCommon(returnDO, deliveryGoodsDO, verifyVO.getMember());
    }

    /**
     * 采购商审核发货单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param returnId:退货id
     * @return :
     **/
    @Override
    public Wrapper<Void> verifyReturnDeliveryGoodsByConsumer(UserLoginCacheDTO user, Long returnId) {

        // 查询退货申请单
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        // 查询发货单
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findFirstById(returnDO.getReturnDeliveryId());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }

        return verifyReturnDeliveryGoodsCommon(returnDO, deliveryGoodsDO, user);
    }

    /**
     * 审核发货单公共方法
     * @author 伍将
     * @date 2021/1/4
     * @param returnDO: 退货单
     * @param deliveryGoodsDO: 发货单
     * @param user: 操作用户
     * @return : 同一数据模型
     **/
    @Transactional
    public Wrapper<Void> verifyReturnDeliveryGoodsCommon(ReturnGoodsDO returnDO, ReturnDeliveryGoodsDO deliveryGoodsDO, UserLoginCacheDTO user) {
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 查询当前退货发货单
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        if (deliveryGoodsDO.getDetailList() == null || deliveryGoodsDO.getDetailList().size() <= 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_ERROR);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())
                && !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 检查发货单商品是否都存在与退货商品中
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        if (returnGoodsDetailList == null || returnGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST);
        }
        // 检查发货单商品是否匹配退货商品
        ReturnDeliveryGoodsDetailDO tempVO = deliveryGoodsDO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !returnGoodsDetailList.stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_ERROR);
        }

/*取消srm关联       // 审核仓库单据
        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(returnDO.getReturnDeliveryId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }*/

        // 更新售后退货商品的退货发货数
        List<ReturnGoodsDetailDO> saveReturnGoodsDetailList = returnGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和发货数
            Double deliveryCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReturnDeliveryGoodsDetailDO::getDeliveryCount).sum();
            // 退货发货数=原有退货发货数+发货数
            item.setDeliveryCount(item.getDeliveryCount() + deliveryCount);
            return true;
        }).collect(Collectors.toList());
        returnGoodsDetailRepository.saveAll(saveReturnGoodsDetailList);

        // 执行外部流转
        int agree = TaskAgreeEnum.REFUSE.getCode();
        if(ProcessUtil.isOfflineLogisticsOfReturnGoods(returnDO.getOuterTaskType())){
            //如果为线下物流或合同线下物流单
            agree = TaskAgreeEnum.NEXT.getCode();
        }else if (null != returnDO.getReturnGoodsAddress() && DeliveryTypeEnum.LOGISTICS.getCode().equals(returnDO.getReturnGoodsAddress().getDeliveryType())) {
            // 如果退货方式为物流,则进入下一步,否则跳过物流流转
            agree = TaskAgreeEnum.AGREE.getCode();
        }
        completeOuterTask(returnDO, agree);

        Integer status = returnDO.getOuterStatus();
        SystemMessageRequest request = new SystemMessageRequest();

        // 走物流流转；内部状态为:待新增物流单
        if (status.equals(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode());
            request.setMessageNotice(MessageTemplateCode.return_goods_logistics);
        }
        // 跳过物流;内部状态为:待退货发货
        else if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
            request.setMessageNotice(MessageTemplateCode.return_goods_return_shipment);
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReplaceGoodsHelpEnum.AUDIT.getMessage(), ReturnGoodsActionEnum.ADD_RETURN_SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.SEND_NO.getMessage() + returnDO.getReturnDeliveryNo()));

        // 售后退货申请待新增退货发货单-1,待新增物流单/待退货发货+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        AfterSaleReturnApplyOperateTypeEnum operateTypeEnum = null;
        if (status.equals(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())) {
            operateTypeEnum = AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_LOGISTICS;
        }
        // 跳过物流;内部状态为:待退货发货
        else if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            operateTypeEnum = AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY;
        }
        noticeVO.setIncreaseOperateType(null != operateTypeEnum ? operateTypeEnum.getCode() : null);
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        request.setMemberId(returnDO.getMemberId());
        request.setRoleId(returnDO.getRoleId());
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 分页查询待新增物流单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeAddLogisticsByConsumer(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货物流
     * @author 伍将
     * @date 2020/9/24
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> addReturnLogistics(AddLogisticsVO addVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(addVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增物流单时，才允许新增物流单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_ADD_LOGISTICS);
        }
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        // 发货单设置物流信息
        deliveryGoodsDO.setLogisticsId(addVO.getLogisticsId());
        deliveryGoodsDO.setLogisticsName(addVO.getLogisticsName());
        deliveryGoodsDO.setLogisticsOrderNo(addVO.getLogisticsOrderNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 退货申请设置内部状态为待确认物流
        returnDO.setReturnLogisticsId(addVO.getLogisticsId());
        returnDO.setReturnLogisticsNo(addVO.getLogisticsOrderNo());
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), returnDO.getId(), returnDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), ( ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + addVO.getLogisticsOrderNo()));

        return Wrapper.success();
    }

    /**
     * 删除退货物流
     * @author 伍将
     * @date 2020/9/29
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> deleteReturnLogistics(Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部为待新增物流单内部状态为待审核物流单时，才允许删除物流单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELETE_LOGISTICS);
        }
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        // 清空物流信息
        deliveryGoodsDO.setLogisticsName("");
        deliveryGoodsDO.setLogisticsOrderNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        // 退货申请设置内部状态为待新增物流
        returnDO.setReturnLogisticsId(0L);
        returnDO.setReturnLogisticsNo("");
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        return Wrapper.success();
    }

    /**
     * 审核退货物流单
     * @author 伍将
     * @date 2020/9/24
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyReturnLogistics(VerifyLogisticsVO verifyVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为采购商待新增物流单，内部状态为采购商待确认物流单或者采购商不接受物流单才允许审核
        if (!ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode().equals(returnDO.getOuterStatus())
                || (!ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getCode().equals(returnDO.getInnerStatus()))) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 物流审核通过时，售后继续工作流
        if (VerifyLogisticsEnum.AGREE.getCode().equals(verifyVO.getIsAccept())) {
            //执行外部
            completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
            Integer status = returnDO.getOuterStatus();

            // 物流审核通过，外部状态为:待确认退货发货
            if (ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
            }
            returnRepository.saveAndFlush(returnDO);

            // 新增采购商内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), returnDO.getId(), returnDO.getInnerStatus(),  ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + returnDO.getReturnLogisticsNo()));

            // 售后退货申请待新增物流单-1,待退货发货+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_LOGISTICS.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            noticeVO.setReduceDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            SystemMessageRequest request = new SystemMessageRequest();
            request.setMemberId(returnDO.getMemberId());
            request.setRoleId(returnDO.getRoleId());
            request.setMessageNotice(MessageTemplateCode.return_goods_return_shipment);
            List<String> params = new ArrayList<>();
            params.add(returnDO.getApplyNo());
            params.add(returnDO.getApplyAbstract());
            request.setParams(params);
            feignService.sendSystemMessage(request);
        }
        // 不接受
        else if (VerifyLogisticsEnum.REFUSE.getCode().equals(verifyVO.getIsAccept())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getCode());
            returnDO.setUpdateTime(System.currentTimeMillis());
            returnRepository.saveAndFlush(returnDO);

            // 新增采购商内部流转记录
            addInnerWorkflowRecord(verifyVO.getMember(), returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.CONSUMER_UN_ACCEPT_LOGISTICS.getMessage(), ReturnGoodsActionEnum.ADD_LOGISTICS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + returnDO.getReturnLogisticsNo()));
        }
        // 确认
        else if (VerifyLogisticsEnum.CONFIRM.getCode().equals(verifyVO.getIsAccept())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONSUMER_TO_BE_CONFIRM_LOGISTICS.getCode());
            returnDO.setUpdateTime(System.currentTimeMillis());
            returnRepository.saveAndFlush(returnDO);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询待退货发货单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeReturnDeliveryGoods(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货发货
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnDeliveryGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }
        if (!deliveryGoodsDO.getStatus().equals(ReturnDeliveryGoodsStatusEnum.TO_BE_CONFIRM_DELIVERY.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 确认退货发货，内部状态为:待新增退货入库单
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getMessage(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getConsumerName(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), "");

        // 售后退货申请待退货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理待新增退货入库单+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_add_return_storage);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        // 更新发货单
        deliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        return Wrapper.success();
    }

    /**
     * 手工退货发货 [废弃：731]
     * @param user: 当前操作用户
     * @param deliveryGoodsVO: 发货信息
     * @return 统一数据模型
     */
    @Deprecated
    @Transactional
    @Override
    public Wrapper<Void> manualReturnDeliveryGoods(UserLoginCacheDTO user, ManualDeliveryGoodsVO deliveryGoodsVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }

        ReturnManualDeliveryGoodsDO manualDeliveryGoodsDO = returnManualDeliveryGoodsRepository.findByReturnId(returnDO.getId());
        if (manualDeliveryGoodsDO == null) {
            manualDeliveryGoodsDO = new ReturnManualDeliveryGoodsDO();
        }
        manualDeliveryGoodsDO.setReturnId(returnDO.getId());
        manualDeliveryGoodsDO.setDeliveryAddress(deliveryGoodsVO.getDeliveryAddress());
        manualDeliveryGoodsDO.setDeliveryTime(deliveryGoodsVO.getDeliveryTime());
        manualDeliveryGoodsDO.setLogisticsName(deliveryGoodsVO.getLogisticsName());
        manualDeliveryGoodsDO.setLogisticsOrderNo(deliveryGoodsVO.getLogisticsOrderNo());
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        manualDeliveryGoodsDO.setCreateTime(System.currentTimeMillis());
        returnManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 待退货收货，内部状态为:待确认退货收货
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsVO.getLogisticsOrderNo()));
        // 新增采购商内部流转记录退货发货
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getConsumerName(), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + deliveryGoodsVO.getLogisticsOrderNo()));

        // 售后退货申请待退货发货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(供应商)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(平台账户)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(0L);
        noticeVO.setRoleId(0L);
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增待退货收货消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_return_receive);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    @Transactional
    @Override
    public Wrapper<Void> manualReturnDeliveryGoodsCommon(UserLoginCacheDTO sysUser, ReturnManualGoodsVO returnManualGoodsVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnManualGoodsVO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }else if(!sysUser.getMemberId().equals(returnDO.getMemberId())||!sysUser.getMemberRoleId().equals(returnDO.getRoleId())){
            throw new BusinessException(ResponseCode.DATA_AUTH_NOT_ALLOWED);
        }
        // 外部状态为待新增退货发货单，内部状态为待审核退货发货单才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())
                && !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_DELIVERY_GOODS);
        }
        //查询退货申请单下的商品信息
        List<ReturnGoodsDetailDO> returnGoodsDetailDOList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        Map<Long, ReturnGoodsDetailDO> productMap = returnGoodsDetailDOList.stream().collect(Collectors.toMap(ReturnGoodsDetailDO::getId, o -> o, (o1, o2) -> o1));
        returnManualGoodsVO.getProductList().forEach(o ->{
            ReturnGoodsDetailDO returnGoodsDetailDO = productMap.get(o.getReturnDetailId());
            if(returnGoodsDetailDO==null){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST,"退货商品不存在");
            }
            if(NumberUtil.sub(returnGoodsDetailDO.getReturnCount(),returnGoodsDetailDO.getDeliveryCount(),o.getReturnCount()).doubleValue()<0){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_COUNT_ERROR);
            }
        });
        Integer oldStatus=returnDO.getOuterStatus();
        //保存手工发货单
        long now = System.currentTimeMillis();
        Integer maxBatchNo = returnDeliveryGoodsRepository.countByReturnId(returnDO.getId());
        ReturnDeliveryGoodsDO returnDeliveryGoodsDO=new ReturnDeliveryGoodsDO();
        returnDeliveryGoodsDO.setReturnId(returnDO.getId());
        returnDeliveryGoodsDO.setBatchNo(maxBatchNo==null?1:maxBatchNo+1);
        returnDeliveryGoodsDO.setCreateTime(now);
        returnDeliveryGoodsDO.setDeliveryTime(returnManualGoodsVO.getDeliveryTime());
        returnDeliveryGoodsDO.setLogisticsOrderNo(returnManualGoodsVO.getLogisticsOrderNo());
        returnDeliveryGoodsDO.setLogisticsName(returnManualGoodsVO.getLogisticsName());
        returnDeliveryGoodsDO.setDeliveryAddress(returnManualGoodsVO.getDeliveryAddress());
        returnDeliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.CONFIRM_DELIVERY.getCode());
        //保存发货单明细
        Set<ReturnDeliveryGoodsDetailDO> deliveryGoodsDetailDOS = returnManualGoodsVO.getProductList().stream().map(o -> {
            ReturnGoodsDetailDO returnGoodsDetailDO = productMap.get(o.getReturnDetailId());
            ReturnDeliveryGoodsDetailDO deliveryGoodsDetailDO = new ReturnDeliveryGoodsDetailDO();
            deliveryGoodsDetailDO.setDeliveryCount(o.getReturnCount());
            deliveryGoodsDetailDO.setReturnCount(o.getReturnCount());
            deliveryGoodsDetailDO.setDeliveryGoods(returnDeliveryGoodsDO);
            deliveryGoodsDetailDO.setReturnGoodsDetailDO(returnGoodsDetailDO);
            deliveryGoodsDetailDO.setProductId(returnGoodsDetailDO.getProductId());
            deliveryGoodsDetailDO.setProductName(returnGoodsDetailDO.getProductName());
            deliveryGoodsDetailDO.setCategory(returnGoodsDetailDO.getCategory());
            deliveryGoodsDetailDO.setBrand(returnGoodsDetailDO.getBrand());
            deliveryGoodsDetailDO.setUnit(returnGoodsDetailDO.getUnit());
            deliveryGoodsDetailDO.setStorageCount(0D);
            deliveryGoodsDetailDO.setOrderNo(returnGoodsDetailDO.getOrderNo());
            //更新退货申请单商品数量
            returnGoodsDetailDO.setDeliveryCount(NumberUtil.add(returnGoodsDetailDO.getDeliveryCount(),o.getReturnCount()));
            return deliveryGoodsDetailDO;
        }).collect(Collectors.toSet());
        returnDeliveryGoodsDO.setDetailList(deliveryGoodsDetailDOS);
        returnDeliveryGoodsRepository.save(returnDeliveryGoodsDO);
        //更新退货申请单的商品表
        returnGoodsDetailRepository.saveAll(productMap.values());
        //退货是否未完成
        boolean isUnfinshed = productMap.values().stream().anyMatch(o -> NumberUtil.sub(o.getReturnCount(), o.getDeliveryCount()) > 0);
        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 待退货收货，内部状态为:待确认退货收货
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        returnDO.setReturnBatch(returnDeliveryGoodsDO.getBatchNo());
        returnRepository.saveAndFlush(returnDO);
        String memo=StringUtils.hasLength(returnManualGoodsVO.getLogisticsOrderNo())?ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() +returnManualGoodsVO.getLogisticsOrderNo():null;
        // 新增采购商外部流转记录
        addOuterWorkflowRecord(sysUser, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReturnGoodsActionEnum.SEND_GOODS.getMessage(),memo );
        // 新增采购商内部流转记录退货发货
        addInnerWorkflowRecord(sysUser, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReturnGoodsActionEnum.SEND_GOODS.getMessage(), memo);

        // 售后退货处理待退货发货-1
        commonReduceOperateNotice(returnDO,oldStatus);
        //操作通知与计数统计
        commonSystemMessageAndIncreaseOperateNotice(returnDO,status);
        return Wrapper.success();
    }

    /**
     * 分页查询待新增退货入库单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeAddReturnGoodsStorage(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 新增退货入库单[旧]
     * @author 伍将
     * @date 2020/9/24
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReturnGoodsStorage(ReturnAddStorageVO addVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(addVO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_ADD_STORAGE);
        }
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_RETURN_STORAGE_GOODS_ERROR);
        }
        ReturnAddGoodsDetailVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_RETURN_STORAGE_GOODS_ERROR);
        }
        // 设置入库数量
        for (ReturnDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReturnAddGoodsDetailVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库单信息
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageId(addVO.getStorageId());
        deliveryGoodsDO.setStorageNo(addVO.getStorageNo());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        returnDO.setReturnStorageId(addVO.getStorageId());
        returnDO.setReturnStorageNo(addVO.getStorageNo());
        // 退货申请设置内部状态为待审核退货入库
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(addVO.getMember(), returnDO.getId(), returnDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage(), (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + addVO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 新增退货收货单
     * @author 伍将
     * @date 2020/9/24
     * @param addVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> addReturnGoodsStorage(UserLoginCacheDTO sysUser, ReturnReceiveAddVO addVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(addVO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_ADD_STORAGE);
        }
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        // 对比入库商品数据
        if (deliveryGoodsDO.getDetailList().size() != addVO.getDetailList().size()) {
            throw new BusinessException(ResponseCode.AS_RETURN_STORAGE_GOODS_ERROR);
        }
        ReturnDeliveryGoodsAddProductVO tempVO = addVO.getDetailList().stream()
                .filter(
                        // 匹配关键字为订单编号+商品id
                        item -> !deliveryGoodsDO.getDetailList().stream()
                                .map(e -> e.getOrderNo() + e.getProductId())
                                .collect(Collectors.toList())
                                .contains(item.getOrderNo() + item.getProductId())
                )
                .findFirst().orElse(null);
        if (tempVO != null) {
            throw new BusinessException(ResponseCode.AS_RETURN_STORAGE_GOODS_ERROR);
        }
        // 设置入库数量
        for (ReturnDeliveryGoodsDetailDO r : deliveryGoodsDO.getDetailList()) {
            for (ReturnDeliveryGoodsAddProductVO o : addVO.getDetailList()) {
                if (o.getProductId().equals(r.getProductId()) && o.getOrderNo().equals(r.getOrderNo())) {
                    r.setStorageCount(o.getCount());
                    break;
                }
            }
        }

        // 发货单设置入库单信息
        deliveryGoodsDO.setStorageTime(addVO.getStorageTime());
        deliveryGoodsDO.setStorageNo(CodeUtils.getInvoicesNo("RK"));
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        //收货单信息保存
        ReturnReceiveGoodsBO receiveGoodsBO=new ReturnReceiveGoodsBO();
        BeanUtils.copyProperties(addVO,receiveGoodsBO);
        deliveryGoodsDO.setReturnReceiveGoodsBO(receiveGoodsBO);
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        returnDO.setReturnStorageId(deliveryGoodsDO.getId());
        returnDO.setReturnStorageNo(deliveryGoodsDO.getStorageNo());
        // 退货申请设置内部状态为待审核退货入库
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(sysUser, returnDO.getId(), returnDO.getOuterStatus(), ReplaceGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage(), (ReturnGoodsHelpEnum.NO.getMessage() + deliveryGoodsDO.getStorageNo()));

        return Wrapper.success();
    }

    /**
     * 删除退货入库单feign[废弃使用:取消srm关联]
     * @author 伍将
     * @date 2020/9/29
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> deleteReturnGoodsStorage(Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部与内部状态皆为：待新增退货入库单时，才允许新增退货入库单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_DELETE_STORAGE);
        }
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }

        // 发货单设置入库单信息
        deliveryGoodsDO.setStorageTime(0L);
        deliveryGoodsDO.setStorageNo("");
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);

        returnDO.setReturnStorageNo("");
        // 退货申请设置内部状态为待新增退货入库
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());

        return Wrapper.success();
    }

    /**
     * 审核退货入收货feign[废弃使用:取消srm关联]
     * @author 伍将
     * @date 2020/9/24
     * @param verifyVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> verifyReturnGoodsStorage(VerifyDeliveryVO verifyVO) {
        // 查询发货单
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findFirstByStorageId(verifyVO.getDataId());
        if (null == deliveryGoodsDO) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }

        // 查询退货申请单
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        // 如果入库单id与当前申请单的入库单id不匹配，则无权审核
        if (!deliveryGoodsDO.getId().equals(returnDO.getReturnStorageId())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        return verifyReturnGoodsStorageCommon(returnDO, verifyVO.getMember());
    }

    /**
     * 供应商审核收货单
     * @author 伍将
     * @date 2021/1/4
     * @param user: 当前操作用户
     * @param returnId:退货id
     * @return : 统一数据模型
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyReturnGoodsStorageBySupplier(UserLoginCacheDTO user, Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        return verifyReturnGoodsStorageCommon(returnDO, user);
    }

    /**
     *
     * @author 伍将
     * @date 2021/1/4
     * @param returnDO: 退货申请单
     * @param user: 当前操作用户
     * @return : 统一数据模型
     **/
    @Transactional
    public Wrapper<Void> verifyReturnGoodsStorageCommon(ReturnGoodsDO returnDO, UserLoginCacheDTO user) {
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待新增退货入库单，内部状态为待审核退货发货单才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_VERIFY_RETURN_GOODS_STORAGE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 审核仓库单据
/*取消srm关联        InvoicesDetailsListRequest requestInvoices = new InvoicesDetailsListRequest();
        requestInvoices.setInvoicesId(returnDO.getReturnStorageId());
        Wrapper<InvoicesDetailsResponse> wrapper = invoicesControllerFeign.invoicesReview(requestInvoices);
        if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.AS_VERIFY_WAREHOUSE_ORDER_ERROR);
        }*/

        //执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 退货入库单审核通过，内部状态为:待确认退货收货
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReplaceGoodsHelpEnum.IS_VERIFY_RETURN_GOODS_STORAGE.getMessage(), ReturnGoodsActionEnum.ADD_IN_STORAGE.getMessage(), (ReplaceGoodsHelpEnum.WAREHOUSING_NO.getMessage() + returnDO.getReturnStorageNo()));

        // 售后退货处理待新增退货入库单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理待退货收货+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);


        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_return_receive);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 分页查询待退货收货
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeReturnReceiveGoods(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货收货
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnReceiveGoods(UserLoginCacheDTO user, Long deliveryId) {
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待退货收货，内部状态为待确认退货收货才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_RETURN_RECEIVE_GOODS);
        }
        deliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());

        // 检查发货单商品是否都存在与退货商品中
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        if (returnGoodsDetailList == null || returnGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST);
        }
        // 更新售后退货统计表中的退货收货数
        returnGoodsDetailList = returnGoodsDetailList.stream().filter(item -> {
            // 根据产品id与订单id求和入库数量
            Double storageCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReturnDeliveryGoodsDetailDO::getStorageCount).sum();
            // 退货收货数=原始退货收货数+现有入库数
            item.setReceiveCount(item.getReceiveCount() + storageCount);
            return true;
        }).collect(Collectors.toList());

        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        returnGoodsDetailRepository.saveAll(returnGoodsDetailList);

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 确认退货收货，内部状态为:待确认退货回单
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReplaceGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getMessage(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");

        // 售后退货申请待确认退货回单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理待退货收货-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getMemberId());
        request.setRoleId(returnDO.getRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_confirm_return);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> confirmManualReturnReceiveGoodsCommon(UserLoginCacheDTO user, Long dataId) {
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findById(dataId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        Integer oldStatus=returnDO.getOuterStatus();
        // 外部状态为待退货收货，内部状态为待确认退货收货才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_RETURN_RECEIVE_GOODS);
        }
        deliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());

        // 检查发货单商品是否都存在与退货商品中
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        if (returnGoodsDetailList == null || returnGoodsDetailList.size() <= 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST);
        }
        //更新发货明细表
        deliveryGoodsDO.getDetailList().forEach(o ->{
            if(o.getStorageCount()<=0) {
                o.setStorageCount(o.getDeliveryCount());
            }
        });
        // 更新售后退货统计表中的退货收货数
        returnGoodsDetailList = returnGoodsDetailList.stream().peek(item -> {
            // 根据产品id与订单id求和入库数量
            Double storageCount = deliveryGoodsDO.getDetailList().stream()
                    .filter(o -> o.getOrderNo().equals(item.getOrderNo()) && o.getProductId().equals(item.getProductId()))
                    .mapToDouble(ReturnDeliveryGoodsDetailDO::getStorageCount).sum();
            // 退货收货数=原始退货收货数+现有入库数
            item.setReceiveCount(NumberUtil.add(item.getReceiveCount(),storageCount));
        }).collect(Collectors.toList());
        returnDeliveryGoodsDetailRepository.saveAll(new ArrayList<>(deliveryGoodsDO.getDetailList()));
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        returnGoodsDetailRepository.saveAll(returnGoodsDetailList);
        //如果是合同订单退货-通知结算服务
        if(ProcessUtil.isSrmContractOfReturnGoods(returnDO.getOrderType())){
            Map<Long, List<ReturnGoodsDetailDO>> returnGoodsDetailDOMap = returnGoodsDetailList.stream().collect(Collectors.groupingBy(o -> o.getContractId()));
            for(Long contractId:returnGoodsDetailDOMap.keySet()) {
                SettlementOrderVO settlementOrderVO = builSettlementOrderVO(returnDO, returnGoodsDetailDOMap.get(contractId), deliveryGoodsDO.getDeliveryTime(), deliveryGoodsDO.getStorageTime(),contractId);
                feignService.notifySrmReturnSettlement(settlementOrderVO);
            }
        }
        int agree=TaskAgreeEnum.NEXT.getCode();
        //判断退货收货是否全部完成
        boolean isUnfinished = returnGoodsDetailList.stream().filter(o ->o.getIsNeedReturn().equals(CommonBooleanEnum.YES.getCode())).anyMatch(r -> NumberUtil.sub(r.getReturnCount(), r.getReceiveCount()) > 0);
        //判断是否手工单
        if(ProcessUtil.isMannualReturnOfReturnGoods(returnDO.getOuterTaskType())) {
            if(isUnfinished){
                //部分完成收货-7
                agree= TaskAgreeEnum.REFUSE.getCode();
            }else{
                if(ProcessEnum.AFTER_SALE_RETURN_GOODS_CONTRACT_MANUAL_DELIVERY.getCode().equals(returnDO.getOuterTaskType())){
                    //合同手工单
                    agree= TaskAgreeEnum.AGREE.getCode();
                }else{
                    //普通手工
                    if(returnDO.getRefundAmount()==0){
                        //无需退款-14
                        agree= TaskAgreeEnum.AGREE_CONDITION2.getCode();
                    }else{
                        //供应商退款-11
                        agree= TaskAgreeEnum.AGREE.getCode();
                    }
                }
            }
        }else if(ProcessUtil.isOfflineLogisticsOfReturnGoods(returnDO.getOuterTaskType())){
            //是否线下物流单
            if(isUnfinished){
                //部分完成收货-5
                agree= TaskAgreeEnum.REFUSE.getCode();
            }else{
                if(ProcessEnum.AFTER_SALE_RETURN_GOODS_VERIFY_CONTRACT_OFFLINE_LOGISTICS.getCode().equals(returnDO.getOuterTaskType())){
                    //合同线下物流-14
                    agree= TaskAgreeEnum.AGREE.getCode();
                }else{
                    //退款金额
                    if(returnDO.getRefundAmount()==0){
                        //无需退款-14
                        agree= TaskAgreeEnum.AGREE_CONDITION2.getCode();
                    }else{
                        //供应商退款-11
                        agree= TaskAgreeEnum.AGREE.getCode();
                    }
                }
            }
        }
        // 执行外部流转
        completeOuterTask(returnDO, agree);
        Integer status = returnDO.getOuterStatus();
        //待新增退货发货单
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            //待新增发货单
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }else if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            //待确认发货
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())){
            //待确认退货回单
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode())){
            //待退款
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())){
            //待确认售后完成
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), "");

        // 售后退货处理待退货收货-1
        commonReduceOperateNotice(returnDO,oldStatus);
        //操作通知与计数统计
        commonSystemMessageAndIncreaseOperateNotice(returnDO,status);
        return Wrapper.success();
    }

    private SettlementOrderVO builSettlementOrderVO(ReturnGoodsDO returnDO,List<ReturnGoodsDetailDO> returnGoodsDetailList,Long deliveryTime,Long storageTime,Long contractId) {
        SettlementOrderVO vo=new SettlementOrderVO();
        vo.setBillId(returnDO.getId());
        vo.setBillNo(returnDO.getApplyNo());
        vo.setBillAbstract(returnDO.getApplyAbstract());
        vo.setBillAmount(BigDecimal.valueOf(returnDO.getRefundAmount()));
        vo.setBillDate(returnDO.getApplyTime());
        vo.setBuyerMemberId(returnDO.getMemberId());
        vo.setBuyerRoleId(returnDO.getRoleId());
        vo.setPayer(returnDO.getConsumerName());
        vo.setVendorMemberId(returnDO.getParentMemberId());
        vo.setVendorRoleId(returnDO.getParentMemberRoleId());
        vo.setPayee(returnDO.getSupplierName());
        vo.setSourceContractId(contractId);
        vo.setDeliveryBatch(returnDO.getReturnBatch());
        vo.setDeliveryNo(returnDO.getReturnDeliveryNo());
        vo.setDeliveryTime(deliveryTime);
        vo.setReceiveNo(returnDO.getReturnStorageNo());
        vo.setReceiveTime(storageTime);
        vo.setOrderStatus(ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage());
        vo.setOrderType(returnDO.getOrderType());
        List<SettlementProductVO> products=returnGoodsDetailList.stream().map(o ->{
            SettlementProductVO productVO=new SettlementProductVO();
            productVO.setProductNo(o.getProductId());
            productVO.setName(o.getProductName());
            productVO.setBrand(o.getBrand());
            productVO.setCategory(o.getCategory());
            productVO.setUnit(o.getUnit());
            productVO.setSpec(o.getType());
            productVO.setReceiveQuantity(BigDecimal.valueOf(o.getReceiveCount()));
            productVO.setTaxRate(BigDecimal.valueOf(o.getTaxRate()));
            productVO.setPrice(BigDecimal.valueOf(o.getPurchasePrice()));
            return productVO;
        }).collect(Collectors.toList());
        vo.setProducts(products);
        return vo;

    }

    private void noticeStatistics(ReturnGoodsDO returnDO){
        // 售后退货申请(采购商)确认售后完成+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
    }

    private void sendSystemMessage(Long memberId,Long roleId,String messageNotice,String applyNo,String applyAbstract){
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(memberId);
        request.setRoleId(roleId);
        request.setMessageNotice(messageNotice);
        List<String> params = new ArrayList<>();
        params.add(applyNo);
        params.add(applyAbstract);
        request.setParams(params);
        feignService.sendSystemMessage(request);
    }

    /**
     * 确认手工退货收货[废弃：731]
     * @author 伍将
     * @date 2020/12/5
     * @param user:
     * @param dataId:
     * @return :
     **/
    @Deprecated
    @Transactional
    @Override
    public Wrapper<Void> confirmManualReturnReceiveGoods(UserLoginCacheDTO user, Long dataId) {
        ReturnGoodsDO returnDO = returnRepository.findById(dataId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待退货收货，内部状态为待确认退货收货才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_RECEIVE_GOODS.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_RETURN_RECEIVE_GOODS);
        }

        ReturnManualDeliveryGoodsDO manualDeliveryGoodsDO = returnManualDeliveryGoodsRepository.findByReturnId(returnDO.getId());
        if (manualDeliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        manualDeliveryGoodsDO.setStatus(ReplaceDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode());
        manualDeliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnManualDeliveryGoodsRepository.saveAndFlush(manualDeliveryGoodsDO);

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 待退款，内部状态为:待退款
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getMessage(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));
        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getSupplierName(), ReturnGoodsActionEnum.RECEIVING_GOODS.getMessage(), (ReplaceGoodsHelpEnum.RECEIVE_LOGISTICS_NO.getMessage() + manualDeliveryGoodsDO.getLogisticsOrderNo()));

        // 售后退货处理待待退货收货-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(供应商)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(平台账户)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(0L);
        noticeVO.setRoleId(0L);
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增供应商待退款消息通知
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);
        // 新增平台待退款消息通知
        request = new SystemMessageRequest();
        request.setMemberId(0L);
        request.setRoleId(0L);
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_platform_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 分页查询待确认退货回单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeConfirmReturnGoodsReceipt(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退货回单
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param deliveryId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmReturnGoodsReceipt(UserLoginCacheDTO user, Long deliveryId) {
        ReturnDeliveryGoodsDO deliveryGoodsDO = returnDeliveryGoodsRepository.findById(deliveryId).orElse(null);
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(deliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许确认退货回单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }
        if (!deliveryGoodsDO.getStatus().equals(ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIVE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 更新发货单
        deliveryGoodsDO.setStatus(ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        deliveryGoodsDO.setUpdateTime(System.currentTimeMillis());
        returnDeliveryGoodsRepository.saveAndFlush(deliveryGoodsDO);
        Integer agree=TaskAgreeEnum.REFUSE.getCode();
        //查询退货商品
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        //判断退货收货是否全部完成
        boolean isUnfinished = returnGoodsDetailList.stream().filter(o ->o.getIsNeedReturn().equals(CommonBooleanEnum.YES.getCode())).anyMatch(r -> NumberUtil.sub(r.getReturnCount(), r.getReceiveCount()) > 0);
        if(!isUnfinished){
        //全部收货完成
            //无退款
            if(returnDO.getRefundAmount()==0){
                agree = TaskAgreeEnum.AGREE_CONDITION2.getCode();
            }else {
                agree = TaskAgreeEnum.AGREE.getCode();
            }
        }
        returnRepository.saveAndFlush(returnDO);
        // 执行外部流转
        completeOuterTask(returnDO, agree);
        Integer status = returnDO.getOuterStatus();
        //外：待(采购商)新增退货发货单 内：待新增退货发货单
        if (ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(status)){
        //外： 待退款
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(status)){
        //外: 待确认售后完成
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getSupplierName(), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");

        //待确认回单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(user.getMemberId());
        noticeVO.setRoleId(user.getMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        if(TaskAgreeEnum.REFUSE.getCode().equals(agree)){
        //部分收货完成 待新增退货发货单+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(user.getMemberId());
            noticeVO.setRoleId(user.getMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            //消息通知 待新增退货发货单
            feignService.sendSystemMessage(user.getMemberId(),user.getMemberRoleId(),MessageTemplateCode.return_goods_shipment,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(TaskAgreeEnum.AGREE.getCode().equals(agree)){
        //全部收货完成：待供应商退款+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            //消息通知 待供应商退款
            feignService.sendSystemMessage(returnDO.getParentMemberId(),returnDO.getParentMemberRoleId(),MessageTemplateCode.return_goods_handle_refund,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(TaskAgreeEnum.AGREE_CONDITION2.getCode().equals(agree)){
        //全部收货完成(无退款)：待确认售后完成+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(user.getMemberId());
            noticeVO.setRoleId(user.getMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            //消息通知 待确认售后完成
            feignService.sendSystemMessage(user.getMemberId(),user.getMemberRoleId(),MessageTemplateCode.return_goods_confirm,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }
        return Wrapper.success();
    }

    /**
     * 继续退货发货
     * @author 伍将
     * @date 2020/12/4
     * @param user:
     * @param returnId :退货id
     * @return :
     **/
    @Override
    public Wrapper<Void> continueReturnDeliveryGoods(UserLoginCacheDTO user, Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许继续退货发货
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_CONTINUE_DELIVERY);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = returnDeliveryGoodsRepository.existsByReturnIdAndStatusNot(returnId, ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_CONTINUE_DELIVERY);
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.REFUSE.getCode());
        Integer status = returnDO.getOuterStatus();
        // 外部待新增退货发货单，内部状态为:待新增退货发货单
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 售后退货申请待确认退货回单-1,待新增退货发货单+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(),  ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getMessage(), ReturnGoodsActionEnum.CONFIRM_COMPLETE.getMessage(), "");

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getMemberId());
        request.setRoleId(returnDO.getRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_shipment);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 确认全部退货回单
     * @author 伍将
     * @date 2020/9/24
     * @param user: 当前登录用户
     * @param returnId: 退货id
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmAllReturnGoodsReceipt(UserLoginCacheDTO user, Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待确认退货回单，内部状态为待确认退货回单才允许确认退货回单
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 校验是否有未确认回单数据
        Boolean isExists = returnDeliveryGoodsRepository.existsByReturnIdAndStatusNot(returnId, ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getCode());
        if (isExists) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_CONFIRM_RETURN_GOODS_RECEIPT);
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.AGREE.getCode());
        Integer status = returnDO.getOuterStatus();
        // 已全部退货并确认退货回单，内部状态为:待退款
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnId, returnDO.getOuterStatus(), ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getMessage(), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");
        // 新增采购商内部流转记录
        addInnerWorkflowRecord(user, returnId, returnDO.getOuterStatus(), ReturnDeliveryGoodsStatusEnum.CONFIRM_RECEIPT.getConsumerName(), ReturnGoodsActionEnum.CONFIRM_RECEIPT.getMessage(), "");

        // 售后退货申请待确认退货回单-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(供应商)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(平台账户)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(0L);
        noticeVO.setRoleId(0L);
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增会员退款消息通知
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);
        // 新增平台退款消息通知
        request = new SystemMessageRequest();
        request.setMemberId(0L);
        request.setRoleId(0L);
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_platform_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 分页查询待退款
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeRefund(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());

        List<Integer> outerStatusList = new ArrayList<>();
        outerStatusList.add(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode());
        outerStatusList.add(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode());

        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("outerStatus").as(Integer.class), ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode()));
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            list.add(criteriaBuilder.in(root.get("outerStatus")).value(outerStatusList));
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), true);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 退款
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param refundVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> refund(UserLoginCacheDTO user, RefundVO refundVO) {
        ReturnGoodsRefundDetailDO refundDetail = returnGoodsRefundDetailRepository.findById(refundVO.getDataId()).orElse(null);
        // 退款明细必须存在
        if (refundDetail == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_REFUND_NOT_EXIST);
        }
        // 外部状态为待退款或退款未到账
        if (!refundDetail.getOuterStatus().equals(ReturnGoodsRefundOuterStatusEnum.TO_BE_REFUND.getCode())
                && !refundDetail.getOuterStatus().equals(ReturnGoodsRefundOuterStatusEnum.REFUND_FAIL.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }
        // 退款金额必须大于0
        if (refundDetail.getRefundAmount() < 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_NEED_REFUND);
        }

        if (OrderPayChannelEnum.OFFLINE.getCode().intValue()==refundDetail.getChannel()) {
            if (refundVO.getPayProve() == null
                    || !StringUtils.hasLength(refundVO.getPayProve().getBankAccount())
                    || !StringUtils.hasLength(refundVO.getPayProve().getBankDeposit())
                    || !StringUtils.hasLength(refundVO.getPayProve().getName())
                    || refundVO.getPayProve().getFileList() == null
                    || refundVO.getPayProve().getFileList().size() <= 0) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_REFUND_PARAM_ERROR);
            }
        }
        ReturnGoodsDetailDO returnGoodsDetail = refundDetail.getReturnGoods();
        if (returnGoodsDetail == null) {
            throw new BusinessException((ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST));
        }
        ReturnGoodsDO returnDO = returnRepository.findById(returnGoodsDetail.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待退款或确认退款未到账，内部状态为未退款、待确认退款、退款成功或退款失败
        if ((!ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(returnDO.getOuterStatus())
                && !ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(returnDO.getOuterStatus()))
                || (!ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.REFUND_FAIL.getCode().equals(returnDO.getInnerStatus()))
        ) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }

        //退款单号  退款明细id+8位随机
        String refundNo=Constants.AS_REFUND_NO_PREFIX+"_"+refundVO.getDataId();
        // 如果当前登录账户为平台账号,支付方式不为平台代收，则无权退款当前数据
        if (UserLoginSourceEnum.BUSINESS_MANAGEMENT_PLATFORM.getCode().equals(user.getLoginSource())) {
            if (!PayRuleConfigurationEnum.PLATFORM.getCode().equals(refundDetail.getPayRuleId())) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
            }
        }
        // 如果当前登录账户为web端登录账号时,支付方式不为会员直接到账或者非同一收款会员,则无权退款当前数据
        else if (user.getLoginSource().equals(UserLoginSourceEnum.BUSINESS_WEB.getCode())) {
            if (!refundDetail.getPayRuleId().equals(PayRuleConfigurationEnum.MEMBER.getCode())
                    || !user.getMemberId().equals(returnDO.getParentMemberId())
                    || !user.getMemberRoleId().equals(returnDO.getParentMemberRoleId())) {
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
            }
        } else {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }

        // 支付渠道：0.积分支付 1.支付宝 2.微信 3.银联 4.余额支付 5.线下支付线上确认 6.授信额度支付 7.货到付款
        // 目前只有线下支付的退款才会主动跳转到下个工作流状态
        long now=System.currentTimeMillis();
        // 积分不允许退款
        if (refundDetail.getChannel() == OrderPayChannelEnum.RIGHT_POINT.getCode().intValue()) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }
        // 支付宝
        else if (refundDetail.getChannel()==OrderPayChannelEnum.ALIPAY.getCode().intValue()) {
            // 退款金额大于0，调用微信退款
            if (refundDetail.getRefundAmount() > 0) {
                Wrapper<Object> aliPayWrapper = feignService.refundByAliPay(returnDO.getParentMemberId(),
                                                                                returnDO.getParentMemberRoleId(),
                                                                                refundDetail.getTransactionPayId(),
                                                                                returnGoodsDetail.getOrderNo(),
                                                                                refundNo,
                                                                                refundDetail.getPayRuleId().intValue(),
                                                                                refundDetail.getRefundAmount());
                if (aliPayWrapper == null || aliPayWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_FAIL.getCode());
                    refundDetail.setRefundRemark(Optional.ofNullable(aliPayWrapper.getData()).map(Object::toString).orElse(""));
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                    return Wrapper.fail(aliPayWrapper);
                } else {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setRefundRemark(null != aliPayWrapper.getData() ? aliPayWrapper.getData().toString() : "");
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    refundDetail.setConfirmTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                    // 更新已退款金额
                    returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                    returnDO.setUpdateTime(now);
                    returnRepository.saveAndFlush(returnDO);

                    // 新增供应商内部流转记录
                    addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
                }
            } else {
                refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setRefundRemark("无需退款");
                refundDetail.setRefundTime(now);
                refundDetail.setUpdateTime(now);
                returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                // 更新已退款金额
                returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                returnDO.setUpdateTime(now);
                returnRepository.saveAndFlush(returnDO);

                // 新增供应商内部流转记录
                addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
            }
        }
        // 微信
        else if (refundDetail.getChannel()==OrderPayChannelEnum.WECHAT_PAY.getCode().intValue()) {

            // 退款金额大于0，调用微信退款
            if (refundDetail.getRefundAmount() > 0) {
                Wrapper<Object> weChatWrapper = feignService.refundByWeChatPay(returnDO.getParentMemberId(),
                                                                                returnDO.getParentMemberRoleId(),
                                                                                refundDetail.getTransactionPayId(),
                                                                                returnGoodsDetail.getOrderNo(),
                                                                                refundNo,
                                                                                refundDetail.getPayAmount(),
                                                                                refundDetail.getPayRuleId().intValue(),
                                                                                refundDetail.getRefundAmount());
                if (weChatWrapper == null || weChatWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_FAIL.getCode());
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                    return Wrapper.fail(weChatWrapper);
                } else {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setRefundRemark(null != weChatWrapper.getData() ? weChatWrapper.getData().toString() : "");
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    refundDetail.setConfirmTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                    // 更新已退款金额
                    returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                    returnDO.setUpdateTime(now);
                    returnRepository.saveAndFlush(returnDO);

                    // 新增供应商内部流转记录
                    addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
                }
            } else {
                refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setRefundRemark("无需退款");
                refundDetail.setRefundTime(now);
                refundDetail.setUpdateTime(now);
                returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                // 更新已退款金额
                returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                returnDO.setUpdateTime(now);
                returnRepository.saveAndFlush(returnDO);

                // 新增供应商内部流转记录
                addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
            }
        }
        // 银联
        else if (refundDetail.getChannel()==OrderPayChannelEnum.UNION_PAY.getCode().intValue()) {
            // todo 尚未对接银联
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }
        // 余额
        else if (refundDetail.getChannel()==OrderPayChannelEnum.ACCOUNT_BALANCE.getCode().intValue()) {
            BalanceRefundRequest refundRequest = new BalanceRefundRequest();
            refundRequest.setPayPlatformTradeCode(refundDetail.getTransactionPayId());
            refundRequest.setTradeMoney(refundDetail.getRefundAmount());
            refundRequest.setRemark(AfterSaleStringEnum.STR_1.getMessage() + returnGoodsDetail.getOrderNo());
            Wrapper<Boolean> balanceRefundWrapper = feignService.balanceRefund(refundRequest);
            if (balanceRefundWrapper == null) {
                return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
            }else if(balanceRefundWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
                return Wrapper.fail(balanceRefundWrapper);
            }

            refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setRefundRemark(balanceRefundWrapper.getData().toString());

            // 更新已退款金额
            returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
            returnDO.setUpdateTime(now);
            returnRepository.saveAndFlush(returnDO);

            refundDetail.setRefundTime(now);
            refundDetail.setUpdateTime(now);
            refundDetail.setConfirmTime(now);
            returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

            // 新增供应商内部流转记录
            addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
        }
        // 线下支付线上确认
        else if (refundDetail.getChannel()==OrderPayChannelEnum.OFFLINE.getCode().intValue()) {

            refundDetail.setPayProve(refundVO.getPayProve());
            refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setRefundTime(now);

//            // 执行外部流转
//            completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
//            // 退款成功，内外部状态皆为:待确认退款
//            returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode());
//            if (ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode().equals(returnDO.getOuterStatus())) {
//                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getCode());
//            }
            returnRepository.saveAndFlush(returnDO);

            refundDetail.setUpdateTime(now);
            returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

            // 新增供应商外部流转记录
            addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsHelpEnum.WAIT.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
            // 新增供应商内部流转记录
            addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");

            // 售后退货申请待确认退款结果+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 售后退货处理(供应商)待退款-1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 售后退货处理(平台账户)待退款-1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(0L);
            noticeVO.setRoleId(0L);
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);

            // 新增消息通知
            SystemMessageRequest request = new SystemMessageRequest();
            request.setMemberId(returnDO.getMemberId());
            request.setRoleId(returnDO.getRoleId());
            request.setMessageNotice(MessageTemplateCode.return_goods_confirm_refund);
            List<String> params = new ArrayList<>();
            params.add(returnDO.getApplyNo());
            params.add(returnDO.getApplyAbstract());
            request.setParams(params);
            feignService.sendSystemMessage(request);
        }
        // 授信
        else if (refundDetail.getChannel()==OrderPayChannelEnum.CREDIT.getCode().intValue()) {
            CreditRefundVO creditRefundVO = new CreditRefundVO();
            creditRefundVO.setPayCode(refundDetail.getTransactionPayId());
            creditRefundVO.setRefundAmount(refundDetail.getRefundAmount());
            creditRefundVO.setMemberId(returnDO.getMemberId());
            creditRefundVO.setMemberRoleId(returnDO.getRoleId());
            creditRefundVO.setParentMemberId(returnDO.getParentMemberId());
            creditRefundVO.setParentMemberRoleId(returnDO.getParentMemberRoleId());
            creditRefundVO.setRemark("订单号：" + returnGoodsDetail.getOrderNo());
            Wrapper<String> creditWrapper = creditControllerFeign.refund(creditRefundVO);
            if (creditWrapper == null) {
                return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
            }else if(creditWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
                return Wrapper.fail(creditWrapper);
            }
            refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setRefundRemark(creditWrapper.getData());

            // 更新已退款金额
            returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
            returnDO.setUpdateTime(now);
            returnRepository.saveAndFlush(returnDO);

            refundDetail.setRefundTime(now);
            refundDetail.setUpdateTime(now);
            refundDetail.setConfirmTime(now);
            returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

            // 新增供应商内部流转记录
            addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
        }
        // 货到付款  月结 账期
        else if (refundDetail.getChannel()==OrderPayChannelEnum.COLLECT_ON_DELIVERY.getCode().intValue()
                ||refundDetail.getChannel()==OrderPayChannelEnum.MONTHLY_SETTLEMENT.getCode().intValue()
                ||refundDetail.getChannel()==OrderPayChannelEnum.ACCOUNT_PERIOD.getCode().intValue()) {
            refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setRefundTime(now);
            refundDetail.setUpdateTime(now);
            returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

            // 更新已退款金额
            returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
            returnDO.setUpdateTime(now);
            returnRepository.saveAndFlush(returnDO);

            // 新增供应商内部流转记录
            addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
        }
        // 通联支付
        else if (refundDetail.getChannel().equals(OrderPayChannelEnum.ALLIN_WECHAT.getCode().longValue()) // 通联支付 - 微信支付
                || refundDetail.getChannel().equals(OrderPayChannelEnum.ALLIN_ALI_PAY.getCode().longValue()) // 通联支付 - 支付宝支付
                || refundDetail.getChannel().equals(OrderPayChannelEnum.ALLIN_QUICK.getCode().longValue()) // 通联支付 - 快捷支付
                || refundDetail.getChannel().equals(OrderPayChannelEnum.ALLIN_UNION.getCode().longValue()) // 通联支付 - 银联支付
                || refundDetail.getChannel().equals(OrderPayChannelEnum.ALLIN_BALANCE.getCode().longValue()) // 通联支付 - 余额支付
        ) {
            // 退款金额大于0，调用通联退款
            if (refundDetail.getRefundAmount() > 0) {
                // 退款订单号
                String tradeNo = returnDO.getApplyNo() +"-"+ RandomStringUtils.random(7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
                // 1.构建调用通联支付requestBody对象
                EAccountRefundRequest requestBody = new EAccountRefundRequest();
                requestBody.setMemberId(returnDO.getMemberId()); // 会员id(收款方)
                requestBody.setMemberRoleId(returnDO.getRoleId()); // 会员角色id(收款方)
                requestBody.setOrderCode(tradeNo); // 退款订单号
                requestBody.setPayCode(refundDetail.getTransactionPayId()); // 原支付订单号
                requestBody.setRefundMoney(refundDetail.getRefundAmount()); // 退款金额
                boolean ontFullAmountFlag = refundDetail.getPayAmount().compareTo(refundDetail.getRefundAmount()) > 0;
                Integer refundType = ontFullAmountFlag ? 1 : 0;
                requestBody.setRefundType(refundType);
                if (ontFullAmountFlag) {
                    requestBody.setMemberId(returnDO.getMemberId()); // 会员id(付款方) 覆盖变换意义
                    requestBody.setMemberRoleId(returnDO.getRoleId()); // 会员角色id(付款方) 覆盖变换意义
                    requestBody.setReMemberId(returnDO.getParentMemberId()); // 会员id(收款方)
                    requestBody.setReMemberRoleId(returnDO.getParentMemberRoleId()); // 会员id(收款方)
                }
                // 2.远端调用【通联支付-退款】
                Wrapper<RefundRespVO> result = feignService.refundByDirectAccount(requestBody);
                if (result == null) {
                    return Wrapper.fail(ResponseCode.SERVICE_PAY_ERROR);
                }
                String refundRemark = result.getData()!=null ? result.getData().toString() : "";
                // 状态码，不是成功，且不是重复订单的错误码
                if (result.getCode()!= ResponseCode.SUCCESS.getCode()
                        /*&& resultCode != AllInPayErrorCodeEnum.DUPLICATE_ORDER_NUMBER.getCode()*/) {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_FAIL.getCode());
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                    return Wrapper.fail(result.getCode(), result.getMessage());
                }
                // 4.更新 退货退款明细
                refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setRefundRemark(refundRemark);
                refundDetail.setRefundTime(now);
                refundDetail.setUpdateTime(now);
                refundDetail.setConfirmTime(now);
                refundDetail.setTradeNo(tradeNo);
                returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                // 5.更新已退款金额
                returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                returnDO.setUpdateTime(now);
                returnRepository.saveAndFlush(returnDO);
                // 6.新增供应商内部流转记录
                addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
            }else {
                refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                refundDetail.setRefundRemark("无需退款");
                refundDetail.setRefundTime(now);
                refundDetail.setUpdateTime(now);
                returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                // 更新已退款金额
                returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                returnDO.setUpdateTime(now);
                returnRepository.saveAndFlush(returnDO);

                // 新增供应商内部流转记录
                addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
            }
        }
        //建行支付
        else if(refundDetail.getChannel()==OrderPayChannelEnum.CCB_B2B.getCode().intValue()){
            // 退款金额大于0，调用建行退款
            if (refundDetail.getRefundAmount() > 0) {
                B2bRefundVO ccbRefundVO=new B2bRefundVO();
                ccbRefundVO.setOrderId(refundDetail.getTransactionPayId());
                ccbRefundVO.setMoney(refundDetail.getRefundAmount().toString());
                ccbRefundVO.setRefundCode(refundNo);
                Wrapper<Boolean> ccbWrapper=feignService.refundByCcbPay(ccbRefundVO);
                if (ccbWrapper == null || ccbWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_FAIL.getCode());
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                    return Wrapper.fail(ccbWrapper);
                } else {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setRefundRemark("");
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    refundDetail.setConfirmTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                    // 更新已退款金额
                    returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                    returnDO.setUpdateTime(now);
                    returnRepository.saveAndFlush(returnDO);

                    // 新增供应商内部流转记录
                    addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
                }
            } else {
                //无需退款
                refundNone(refundDetail,now,user,returnDO);
            }
        }
        //建行数字货币支付
        else if(refundDetail.getChannel()==OrderPayChannelEnum.CCB_DIGITAL.getCode().intValue()){
            // 退款金额大于0，调用建行数字货币退款
            if (refundDetail.getRefundAmount() > 0) {
                DigitalRefundVO ccbRefundVO=new DigitalRefundVO();
                ccbRefundVO.setOrderCode(refundDetail.getTransactionPayId());
                ccbRefundVO.setMoney(BigDecimal.valueOf(refundDetail.getRefundAmount()));
                ccbRefundVO.setRefundSn(refundNo);
                String payTime = DateUtil.date(refundDetail.getPayTime()).toString(DatePattern.PURE_DATE_PATTERN);
                ccbRefundVO.setOrderStartTime(payTime);
                ccbRefundVO.setOrderEndTime(payTime);
                Wrapper<Boolean> ccbWrapper=feignService.refundByCcbDigitalPay(ccbRefundVO);
                if (ccbWrapper == null || ccbWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_FAIL.getCode());
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
                    return Wrapper.fail(ccbWrapper);
                } else {
                    refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
                    refundDetail.setRefundRemark("");
                    refundDetail.setRefundTime(now);
                    refundDetail.setUpdateTime(now);
                    refundDetail.setConfirmTime(now);
                    returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

                    // 更新已退款金额
                    returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
                    returnDO.setUpdateTime(now);
                    returnRepository.saveAndFlush(returnDO);

                    // 新增供应商内部流转记录
                    addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");
                }
            } else {
                //无需退款
                refundNone(refundDetail,now,user,returnDO);
            }
        }
        // 不支持的退款方式
        else {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }
        // 检查完成退款
        try{
            CommonIdVO commonIdVO = new CommonIdVO();
            commonIdVO.setDataId(refundDetail.getReturnId());
            completeRefund(user, commonIdVO);
            confirmAllRefund(user, refundDetail.getReturnId());
        }catch (BusinessException ignored) {
            logger.error("调用完成退款，的错误信息：{}", ignored.getMessage());
        }

        //退款完成，通知订单服务修改退款金额
        Long orderId = refundDetail.getOrderId();
        Long productId = returnGoodsDetail.getOrderRecordId();
        Long skuId = returnGoodsDetail.getSkuId();
        Double refundAmount = refundDetail.getRefundAmount();
        OrderReturnAmountUpdateVO orderReturnAmountUpdateVO =new OrderReturnAmountUpdateVO(orderId,productId,skuId,refundAmount);
        orderFeignService.updateAfterSaleOrderProductAmount(orderReturnAmountUpdateVO);

        return Wrapper.success();
    }

    private void refundNone(ReturnGoodsRefundDetailDO refundDetail,Long now,UserLoginCacheDTO user,ReturnGoodsDO returnDO){
        refundDetail.setInnerStatus(ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode());
        refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
        refundDetail.setRefundRemark("无需退款");
        refundDetail.setRefundTime(now);
        refundDetail.setUpdateTime(now);
        returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);
        // 更新已退款金额
        returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
        returnDO.setUpdateTime(now);
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商内部流转记录
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");

    }

    /**
     * 完成退款
     * @author 伍将
     * @date 2020/12/9
     * @param user:
     * @param commonIdVO:
     * @return :
     **/
    @Override
    public Wrapper<Void> completeRefund(UserLoginCacheDTO user, CommonIdVO commonIdVO) {

        ReturnGoodsDO returnDO = returnRepository.findById(commonIdVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待退款或确认退款未到账，内部状态为未退款、退款成功或退款失败
        if ((!ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(returnDO.getOuterStatus())
                && !ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(returnDO.getOuterStatus()))
                || (!ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getCode().equals(returnDO.getInnerStatus())
                && !ReturnGoodsInnerStatusEnum.REFUND_FAIL.getCode().equals(returnDO.getInnerStatus()))
        ) {
            if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode().equals(returnDO.getOuterStatus())){
                throw new BusinessException(ResponseCode.AS_RETURN_GOODS_WAIT_FOR_PURCHASE_CONFIRM);
            }
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_REFUND);
        }

        // 验证是否存在未退款数据
        Long count = returnGoodsRefundDetailRepository.getReturnUnRefund(returnDO.getId());
        if (count > 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_COMPLETE_REFUND);
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 退款成功，内外部状态皆为:待确认退款
        if (ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode().equals(status)) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增供应商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getConsumerDescribe(), ReturnGoodsActionEnum.MONEY_BACK.getMessage(), "");

        // 售后退货申请待确认退款结果+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(供应商)待退款-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(平台账户)待退款-1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(0L);
        noticeVO.setRoleId(0L);
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getMemberId());
        request.setRoleId(returnDO.getRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_confirm_refund);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 分页查询待确认退款
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeConfirmRefund(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 确认退款
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param confirmRefundVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmRefund(UserLoginCacheDTO user, ReturnGoodsConfirmRefundVO confirmRefundVO) {
        if (!confirmRefundVO.getIsReceipt().equals(CommonBooleanEnum.YES.getCode())
                && !confirmRefundVO.getIsReceipt().equals(CommonBooleanEnum.NO.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_CONFIRM_REFUND_PARA_ERROR);
        }
        ReturnGoodsRefundDetailDO refundDetail = returnGoodsRefundDetailRepository.findById(confirmRefundVO.getRefundId()).orElse(null);
        if (refundDetail == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_REFUND_NOT_EXIST);
        }
        ReturnGoodsDetailDO returnGoodsDetail = refundDetail.getReturnGoods();
        if (returnGoodsDetail == null) {
            throw new BusinessException((ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST));
        }
        ReturnGoodsDO returnDO = returnRepository.findById(returnGoodsDetail.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 内外部状态皆为待确认退款
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_CONFIRM_REFUND);
        }
        // 内部状态为退款成功
        if (!ReturnGoodsRefundInnerStatusEnum.REFUND_SUCCEED.getCode().equals(refundDetail.getInnerStatus())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_CONFIRM_REFUND);
        }
        long now=System.currentTimeMillis();
        if (CommonBooleanEnum.YES.getCode().equals(confirmRefundVO.getIsReceipt())) {
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_SUCCEED.getCode());
            refundDetail.setConfirmTime(now);
        } else {
            refundDetail.setOuterStatus(ReturnGoodsRefundOuterStatusEnum.REFUND_FAIL.getCode());
        }
        refundDetail.setUpdateTime(now);
        returnGoodsRefundDetailRepository.saveAndFlush(refundDetail);

        if (CommonBooleanEnum.YES.getCode().equals(confirmRefundVO.getIsReceipt())) {
            // 更新已退款金额:已退款=原有已退款+现退款金额
            returnDO.setRefunded(returnDO.getRefunded() + refundDetail.getRefundAmount());
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.REFUSE.getCode());
        Integer status = returnDO.getOuterStatus();
        // 部分退款成功，内外部状态皆为:待退款
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode())) {
            // 退款成功，设置内部状态为退款成功
            if (CommonBooleanEnum.YES.getCode().equals(confirmRefundVO.getIsReceipt())) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.REFUND_SUCCEED.getCode());
            }
            // 退款失败，设置外部状态为确认退款未到账
            else {
                returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode());
            }
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getMessage(), ReturnGoodsActionEnum.CONFIRM_MONEY_BACK.getMessage(), "");
        // 新增采购商内部流转记录确认退款到账
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsHelpEnum.REFUND_SUCCEED.getMessage(), ReturnGoodsActionEnum.CONFIRM_MONEY_BACK.getMessage(), "");

        // 售后退货申请待确认退款结果-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(供应商)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getParentMemberId());
        noticeVO.setRoleId(returnDO.getParentMemberRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);
        // 售后退货处理(平台账户)待退款+1
        noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(0L);
        noticeVO.setRoleId(0L);
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
        noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增会员退款消息通知
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getParentMemberId());
        request.setRoleId(returnDO.getParentMemberRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);
        // 新增平台退款消息通知
        request = new SystemMessageRequest();
        request.setMemberId(0L);
        request.setRoleId(0L);
        request.setMessageNotice(MessageTemplateCode.return_goods_handle_platform_refund);
        request.setParams(params);
        feignService.sendSystemMessage(request);

        return Wrapper.success();
    }

    /**
     * 确认全部退款
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param returnId:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmAllRefund(UserLoginCacheDTO user, Long returnId) {
        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 内外部状态皆为待确认退款
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode())
                || !returnDO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_REFUND.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_CONFIRM_REFUND);
        }
        // 验证是否存在未退款数据
        Long count = returnGoodsRefundDetailRepository.getReturnUnCompleteRefund(returnDO.getId());
        if (count > 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_CONFIRM_REFUND);
        }

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.AGREE.getCode());
        Integer status = returnDO.getOuterStatus();
        // 全部退款成功，内外部状态皆为:待确认售后完成
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(status), ReturnGoodsActionEnum.CONFIRM_MONEY_BACK.getMessage(), "");

        // 售后退货申请待确认退款结果-1,待确认售后完成+1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
        noticeVO.setIncreaseDataId(returnDO.getId());
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);

        // 新增消息通知
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(returnDO.getMemberId());
        request.setRoleId(returnDO.getRoleId());
        request.setMessageNotice(MessageTemplateCode.return_goods_confirm);
        List<String> params = new ArrayList<>();
        params.add(returnDO.getApplyNo());
        params.add(returnDO.getApplyAbstract());
        request.setParams(params);
        feignService.sendSystemMessage(request);

        try {
            confirmAllRefund(user, returnDO.getId());
        } catch (BusinessException ignored) {
            logger.error("调用认全部退款，的错误信息：{}", ignored.getMessage());
        }

        return Wrapper.success();
    }

    /**
     * 分页查询待待确认售后完成
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param pageVO:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO>>
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeComplete(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.ALL.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    private void noticeRefundCouponSettleAccount(ReturnGoodsDO returnDO){
        //查询退货详情
        List<ReturnGoodsDetailDO> returnDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());

        //查询order-feign获得使用了平台优惠券的订单项信息
        List<Long> orderIdList = returnDetailList.stream().map(ReturnGoodsDetailDO::getOrderId).collect(Collectors.toList());
        OrderFeignIdsVO orderVO=new OrderFeignIdsVO();
        orderVO.setOrderIds(orderIdList);
        Wrapper<List<OrderProductCouponFeignVO>> orderProductCouponAmounts = feignService.findOrderProductCouponAmounts(orderVO);
        if(orderProductCouponAmounts.getCode()!=ResponseCode.SUCCESS.getCode()){
            throw new BusinessException(ResponseCode.FEIGN_SERVICE_ERROR);
        }
        if(CollectionUtil.isEmpty(orderProductCouponAmounts.getData())){
            return;
        }
        Map<Long, OrderProductCouponFeignVO> orderRecordMap = orderProductCouponAmounts.getData().stream().collect(Collectors.toMap(OrderProductCouponFeignVO::getOrderProductId, v -> v, (v1, v2) -> v1));
        PlatformCouponSettlementRequestVO requestVO=new PlatformCouponSettlementRequestVO();
        requestVO.setMemberId(returnDO.getParentMemberId());
        requestVO.setRoleId(returnDO.getParentMemberRoleId());
        requestVO.setSettlementName(returnDO.getSupplierName());
        List<PlatformCouponSettlementDetailRequestVO> detailRequestVOS = returnDetailList.stream().filter(v->orderRecordMap.get(v.getOrderRecordId())!=null).map(o -> {
            PlatformCouponSettlementDetailRequestVO detailRequestVO = new PlatformCouponSettlementDetailRequestVO();
            detailRequestVO.setReturnDetailId(o.getId());
            detailRequestVO.setOrderNo(returnDO.getApplyNo());
            detailRequestVO.setOrderType(returnDO.getOrderType());
            detailRequestVO.setOrderAbstract(returnDO.getApplyAbstract());
            detailRequestVO.setOrderAmount(returnDO.getRefundAmount());
            detailRequestVO.setSettlementOrderType(SettlementOrderTypeEnum.RETURN_GOODS.getCode());
            detailRequestVO.setOrderTime(returnDO.getApplyTime());
            OrderProductCouponFeignVO orderProductCouponFeignVO = orderRecordMap.get(o.getOrderRecordId());
            detailRequestVO.setCouponId(orderProductCouponFeignVO.getPlatformCouponId());
            //退货数量占比
            double rate = NumberUtil.div(o.getReturnCount(), o.getPurchaseCount(), Constants.AS_SCALE);
            detailRequestVO.setCouponAmount(NumberUtil.mul(rate,orderProductCouponFeignVO.getPlatformCouponAmount().doubleValue()));
            return detailRequestVO;
        }).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(detailRequestVOS)) {
            requestVO.setDetails(detailRequestVOS);
            feignService.sendMsgToSettleAccountMQ(SettleAccountQueueMessageTypeEnum.PLATFORM_COUPON_SETTLEMENT.getCode(), JSONUtil.toJsonStr(requestVO));
        }
    }

    /**
     * 确认售后完成
     * @author 伍将
     * @date 2020/9/24
     * @param user:
     * @param completeVO:
     * @return : com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> confirmComplete(UserLoginCacheDTO user, ReturnConfirmCompleteVO completeVO) {
        if (completeVO.getEvaluate() == null) {
            throw new BusinessException(ResponseCode.AS_EVALUATE_PARAM_ERROR);
        }
        if (completeVO.getEvaluate().getLevel() < EvaluateLevelEnum.ONE.getCode()
                || completeVO.getEvaluate().getLevel() > EvaluateLevelEnum.FIVE.getCode()) {
            throw new BusinessException(ResponseCode.AS_EVALUATE_LEVEL_ERROR);
        }
        // 当选择2分或1分时，售后评价为必填
        if (completeVO.getEvaluate().getLevel() <= EvaluateLevelEnum.TOW.getCode()
                && !StringUtils.hasLength(completeVO.getEvaluate().getContent())) {
            throw new BusinessException(ResponseCode.AS_EVALUATE_CONTENT_EMPTY);
        }

        ReturnGoodsDO returnDO = returnRepository.findById(completeVO.getReturnId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_CONFIRM_COMPLETE);
        }

        //退货完成通知结算退平台优惠券金额
        noticeRefundCouponSettleAccount(returnDO);

        // 执行外部流转
        completeOuterTask(returnDO, TaskAgreeEnum.NEXT.getCode());
        Integer status = returnDO.getOuterStatus();
        // 确认换货收货，内部状态为:待确认换货回单
        if (status.equals(ReturnGoodsOuterStatusEnum.COMPLETE.getCode())) {
            returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.CONFIRM_COMPLETE.getCode());
        }
        returnRepository.saveAndFlush(returnDO);

        // 新增采购商外内部流转记录
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(status), ReturnGoodsActionEnum.CONFIRM_COMPLETE.getMessage(), "");
        // 新增采购商内部流转记录确认售后完成
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), RepairGoodsInnerStatusEnum.CONFIRM_COMPLETE.getMessage(), ReturnGoodsActionEnum.CONFIRM_COMPLETE.getMessage(), "");

        // 新增评价
        EvaluateDO evaluateDO = new EvaluateDO();
        evaluateDO.setAfterSaleId(returnDO.getId());
        evaluateDO.setAfterSaleType(AfterSaleTypeEnum.RETURN.getCode());
        evaluateDO.setLevel(completeVO.getEvaluate().getLevel());
        evaluateDO.setContent(completeVO.getEvaluate().getContent());
        evaluateDO.setEvaluateTime(System.currentTimeMillis());
        evaluateRepository.saveAndFlush(evaluateDO);

        // 完成售后之后调用内部评价接口
        MemberFeignAfterSaleCommentVO commentVO = new MemberFeignAfterSaleCommentVO();
        commentVO.setCommentMemberId(returnDO.getMemberId());
        commentVO.setCommentRoleId(returnDO.getRoleId());
        commentVO.setReceivedMemberId(returnDO.getParentMemberId());
        commentVO.setReceivedRoleId(returnDO.getParentMemberRoleId());
        commentVO.setAfterSaleTime(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
        commentVO.setStar(evaluateDO.getLevel());
        commentVO.setComment(evaluateDO.getContent());
        commentVO.setOrderNo(returnDO.getApplyNo());
        List<ReturnGoodsDetailDO> detailDOS = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        StringBuilder productStr = new StringBuilder();
        for (ReturnGoodsDetailDO detail : detailDOS) {
            productStr.append("售后商品：").append(detail.getProductName()).append("\n");
            productStr.append("售后处理数量：").append(detail.getReturnCount()).append(detail.getUnit()).append("\n");
        }
        commentVO.setProduct(productStr.toString());
        feignService.addMemberEvaluate(commentVO);

        // 售后退货申请待确认售后完成-1
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        noticeVO.setMemberId(returnDO.getMemberId());
        noticeVO.setRoleId(returnDO.getRoleId());
        noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
        noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
        noticeVO.setReduceDataId(returnDO.getId());
        feignService.addSysOperateNotice(noticeVO);


        return Wrapper.success();
    }

    /**
     * 分页查询列表页面搜索条件内容
     * @author 伍将
     * @date 2020/10/17
     * @param user:
     * @return : com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsPageItemsVO>
     **/
    @Override
    public Wrapper<ReturnGoodsPageItemsVO> pageItems(UserLoginCacheDTO user) {

        ReturnGoodsPageItemsVO result = new ReturnGoodsPageItemsVO();
        // 组装外部状态
        result.setOuterStatusList(convertOuterStatus());
        // 组装内部状态
        result.setInnerStatusList(convertInnerStatus());

        return Wrapper.success(result);
    }

    /**
     * 获取外部状态列表
     * @author 伍将
     * @date 2020/10/17
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.PageItemVO>
     **/
    private List<PageItemVO> convertOuterStatus() {
        return Arrays.stream(ReturnGoodsOuterStatusEnum.values()).map(r -> {
            PageItemVO status = new PageItemVO();
            status.setStatus(r.getCode());
            status.setName(r.getMessage());
            return status;
        }).collect(Collectors.toList());
    }

    /**
     * 获取内部状态列表
     * @author 伍将
     * @date 2020/10/17
     * @return : java.util.List<com.ssy.lingxi.after.sale.model.vo.response.PageItemVO>
     **/
    private List<PageItemVO> convertInnerStatus() {
        return Arrays.stream(ReturnGoodsInnerStatusEnum.values()).map(r -> {
            PageItemVO status = new PageItemVO();
            status.setStatus(r.getCode());
            status.setName(r.getMessage());
            return status;
        }).collect(Collectors.toList());
    }

    /**
     * 平台分页查询退货申请
     * @author 伍将
     * @date 2020/12/7
     * @param user:
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageByPlatform(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (pageVO.getInnerStatus() != null
                    && !pageVO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), false);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 平台分页查询退货退款申请
     * @author 伍将
     * @date 2020/12/7
     * @param user:
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageRefundByPlatform(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {

        List<Integer> outerStatusList = new ArrayList<>();
        outerStatusList.add(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode());
        outerStatusList.add(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode());
        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            list.add(criteriaBuilder.in(root.get("outerStatus")).value(outerStatusList));
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent(), true);

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 平台查询退货申请详情
     * @author 伍将
     * @date 2020/12/7
     * @param user:
     * @param returnId:
     * @return :
     **/
    @Override
    public Wrapper<ReturnGoodsDetailVO> getDetailPlatform(UserLoginCacheDTO user, Long returnId) {
        return getDetail(user, returnId, true);
    }

    /**
     * 物流服务-分页获取待新增物流申请单
     * @author 伍将
     * @date 2020/12/8
     * @param user:
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ApplyOrderQueryVO>> pageByLogistics(UserLoginCacheDTO user, ApplyOrderPageVO pageVO) {

        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));

            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode()));

            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getMemberName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getMemberName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ApplyOrderQueryVO> resultList = result.getContent().stream().map(r -> {
            ApplyOrderQueryVO queryVO = new ApplyOrderQueryVO();
            queryVO.setApplyId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            queryVO.setApplyAbstract(r.getApplyAbstract());
            queryVO.setMemberName(r.getConsumerName());
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setDeliveryId(r.getReturnDeliveryId());
            queryVO.setDeliveryNo(r.getReturnDeliveryNo());
            if (r.getReturnGoodsAddress() != null) {
                queryVO.setReceiveId(r.getReturnGoodsAddress().getReceiveId());
                queryVO.setReceiveAddress(r.getReturnGoodsAddress().getReceiveAddress());
                queryVO.setReceiveUserName(r.getReturnGoodsAddress().getReceiveUserName());
                queryVO.setReceiveUserTel(r.getReturnGoodsAddress().getReceiveUserTel());
            }
            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 物流服务-获取退货申请单详情
     * @author 伍将
     * @date 2020/12/9
     * @param returnId: 售后id
     * @return :
     **/
    @Override
    public Wrapper<ApplyOrderQueryVO> pageDetailByLogistics(Long returnId) {

        ReturnGoodsDO returnDO = returnRepository.findById(returnId).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        ApplyOrderQueryVO result = new ApplyOrderQueryVO();
        result.setApplyId(returnDO.getId());
        result.setApplyNo(returnDO.getApplyNo());
        result.setApplyAbstract(returnDO.getApplyAbstract());
        result.setMemberName(returnDO.getConsumerName());
        result.setApplyTime(DateUtil.format(DateUtil.date(returnDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
        if (returnDO.getReturnGoodsAddress() != null) {

            result.setReceiveId(returnDO.getReturnGoodsAddress().getReceiveId());
            result.setReceiveAddress(returnDO.getReturnGoodsAddress().getReceiveAddress());
            result.setReceiveUserName(returnDO.getReturnGoodsAddress().getReceiveUserName());
            result.setReceiveUserTel(returnDO.getReturnGoodsAddress().getReceiveUserTel());
            result.setReceiveMemberId(returnDO.getParentMemberId());
            result.setReceiveRoleId(returnDO.getParentMemberRoleId());

            result.setSendId(returnDO.getReturnGoodsAddress().getSendId());
            result.setSendAddress(returnDO.getReturnGoodsAddress().getSendAddress());
            result.setSendUserName(returnDO.getReturnGoodsAddress().getSendUserName());
            result.setSendUserTel(returnDO.getReturnGoodsAddress().getSendUserTel());
            result.setSendMemberId(returnDO.getMemberId());
            result.setSendRoleId(returnDO.getRoleId());
        }
        result.setDeliveryId(returnDO.getReturnDeliveryId());
        result.setDeliveryNo(returnDO.getReturnDeliveryNo());
        result.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()));
        result.setConsumerName(returnDO.getConsumerName());
        result.setSupplierName(returnDO.getSupplierName());
        return Wrapper.success(result);
    }

    /**
     * 仓库服务-分页查询待新增退货发货单
     * @author 伍将
     * @date 2020/12/22
     * @param user:
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeAddReturnDeliveryByWarehouse(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, false, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 仓库服务-分页查询待新增退货入库单
     * @author 伍将
     * @date 2020/12/22
     * @param user:
     * @param pageVO:
     * @return :
     **/
    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeAddReturnStorageByWarehouse(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());

        return pageList(returnGoodsPageVO, true, user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 根据退货申请单查询对应订单
     * @author 伍将
     * @date 2021/1/27
     * @param applyNo: 退货申请单号
     * @return 订单号列表
     **/
    @Override
    public Wrapper<List<String>> getOrderList(String applyNo) {
        ReturnGoodsDO returnDO = returnRepository.findByApplyNo(applyNo);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        List<ReturnGoodsDetailDO> returnGoodsDetailList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());

        List<String> resultList = returnGoodsDetailList.stream().map(ReturnGoodsDetailDO::getOrderNo).distinct().collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 查询是否允许支付
     * @author 伍将
     * @date 2021/1/28
     * @param payVO:请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<Boolean> isAllowPay(AllowPayVO payVO) {
        Long count = returnGoodsRefundDetailRepository.getOrderUnRefundCount(payVO.getOrderId());
        if (count > 0) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_ORDER_NOT_ALLOW_PAY);
        }
        return Wrapper.success(true);
    }

    /**
     * 根据退货订单ids,查询退货订单信息（状态）列表
     * @param returnGoodsIds 退货订单ids
     * @return 退货订单信息（状态）列表
     */
    @Override
    public Wrapper<List<ReturnGoodsInfoVO>> getOrderInfoListByIds(List<Long> returnGoodsIds) {
        if(CollectionUtil.isEmpty(returnGoodsIds)){
            return Wrapper.success();
        }
        List<ReturnGoodsDO> allById = returnRepository.findAllById(returnGoodsIds);
        if(CollectionUtil.isEmpty(allById)){
            return Wrapper.success();
        }
        List<ReturnGoodsInfoVO> returnGoodsInfoVOList = allById.stream().map(o -> {
            ReturnGoodsInfoVO vo = new ReturnGoodsInfoVO();
            vo.setReturnId(o.getId());
            vo.setApplyNo(o.getApplyNo());
            vo.setOuterStatus(o.getOuterStatus());
            vo.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(o.getOuterStatus()));
            return vo;
        }).collect(Collectors.toList());
        return Wrapper.success(returnGoodsInfoVOList);
    }

    @Override
    public Wrapper<List<ReturnGoodsDetailListResponse>> getOrderListByContractId(ReturnListGoodsDetailVO vo) {
        QReturnGoodsDetailDO returnGoodsDetailDO=QReturnGoodsDetailDO.returnGoodsDetailDO;
        QReturnGoodsDO returnGoodsDO=QReturnGoodsDO.returnGoodsDO;

        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(returnGoodsDetailDO.contractId.eq(vo.getContractId()));
        //退款订单编号
        if (StringUtils.hasLength(vo.getApplyNo())) {
            predicates.and(returnGoodsDO.applyNo.eq(vo.getApplyNo()));
        }
        //订单摘要
        if (StringUtils.hasLength(vo.getApplyAbstract())) {
            predicates.and(returnGoodsDO.applyNo.like("%" +vo.getApplyAbstract()+"%"));
        }
        //订单时间
        if (Objects.nonNull(vo.getStartTime())) {
            predicates.and(returnGoodsDO.applyTime.goe(vo.getStartTime()));
        }
        if (Objects.nonNull(vo.getEndTime())) {
            predicates.and(returnGoodsDO.applyTime.loe(vo.getEndTime()));
        }
        JPAQuery<ReturnGoodsDetailListResponse> data = jpaQueryFactory
                .select(Projections.bean(ReturnGoodsDetailListResponse.class,
                        returnGoodsDO.id.as("orderId"),
                        returnGoodsDO.applyNo,
                        returnGoodsDO.applyAbstract,
                        returnGoodsDO.outerStatus,
                        returnGoodsDO.applyTime.as("orderTime"),
                        returnGoodsDetailDO.purchaseCount,
                        returnGoodsDetailDO.purchasePrice,
                        returnGoodsDetailDO.isHasTax,
                        returnGoodsDetailDO.taxRate,
                        returnGoodsDetailDO.returnCount
                        ))
                .from(returnGoodsDetailDO)
                .leftJoin(returnGoodsDO)
                .on(returnGoodsDetailDO.returnId.eq(returnGoodsDO.id))
                .where(predicates);
        List<ReturnGoodsDetailListResponse> fetch = data.fetch();
        if(CollectionUtil.isNotEmpty(fetch)){
            fetch.forEach(o ->{
                o.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(o.getOuterStatus()));
                o.setOrderTypeName(ContractOrderTypeEnum.RETURN_GOODS.getMessage());
                o.setOrderAmount(NumberUtil.mul(o.getReturnCount(),o.getPurchasePrice()));
            });
            fetch = fetch.stream().collect(Collectors.groupingBy(ReturnGoodsServiceImpl::fetchGroupKey)).values().stream().map(o -> {
                ReturnGoodsDetailListResponse response = new ReturnGoodsDetailListResponse();
                BeanUtils.copyProperties(o.get(0), response);
                if (o.size() > 1) {
                    response.setOrderAmount(o.stream().reduce((v1, v2) -> {
                                v1.setOrderAmount(NumberUtil.add(v1.getOrderAmount(), v2.getOrderAmount()));
                                return v1;
                            }).get().getOrderAmount()
                    );
                }
                return response;
            }).collect(Collectors.toList());
        }
        return Wrapper.success(fetch);
    }

    private static String fetchGroupKey(ReturnGoodsDetailListResponse response) {
        return response.getOrderId()+":"+response.getIsHasTax()+":"+response.getTaxRate();
    }

    @Override
    public Wrapper<PageData<AfterSaleGoodsIMQueryVO>> pageByIM(UserLoginCacheDTO user, AfterSaleGoodsIMPageVO request) {
        // 查询表实体
        QReturnGoodsDO returnGoodsDO = QReturnGoodsDO.returnGoodsDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        Long memberId,roleId,parentMemberId,parentMemberRoleId;
        if(RoleTypeEnum.SERVICE_PROVIDER.getCode().equals(user.getMemberRoleType())){
            memberId=request.getMemberId();
            roleId  =request.getMemberRoleId();
            parentMemberId=user.getMemberId();
            parentMemberRoleId=user.getMemberRoleId();
        }else{
            memberId=user.getMemberId();
            roleId  =user.getMemberRoleId();
            parentMemberId=request.getMemberId();
            parentMemberRoleId=request.getMemberRoleId();
        }
        predicates.and(returnGoodsDO.memberId.eq(memberId));
        if(roleId!=null) {
            predicates.and(returnGoodsDO.roleId.eq(roleId));
        }
        predicates.and(returnGoodsDO.parentMemberId.eq(parentMemberId));
        if(parentMemberRoleId!=null) {
            predicates.and(returnGoodsDO.parentMemberRoleId.eq(parentMemberRoleId));
        }
        if (StringUtils.hasLength(request.getApplyNo())) {
            predicates.and(returnGoodsDO.applyNo.eq(request.getApplyNo()));
        }
        if (StringUtils.hasLength(request.getApplyAbstract())) {
            predicates.and(returnGoodsDO.applyAbstract.like("%"+request.getApplyAbstract()+"%"));
        }
        if (Objects.nonNull(request.getStartTime())) {
            predicates.and(returnGoodsDO.createTime.goe(request.getStartTime()));
        }
        if (Objects.nonNull(request.getEndTime())) {
            predicates.and(returnGoodsDO.createTime.loe(request.getEndTime()));
        }

        JPAQuery<AfterSaleGoodsIMQueryVO> query = jpaQueryFactory
                .select(Projections.bean(AfterSaleGoodsIMQueryVO.class,
                        returnGoodsDO.applyNo,
                        returnGoodsDO.applyAbstract,
                        returnGoodsDO.createTime.as("applyTime"),
                        returnGoodsDO.outerStatus.as("status"),
                        returnGoodsDO.orderType)
                )
                .from(returnGoodsDO)
                .where(predicates);

        long totalCount = query.fetchCount();
        List<AfterSaleGoodsIMQueryVO> responses = query.orderBy(returnGoodsDO.createTime.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize())
                .fetch();
        if(CollectionUtil.isNotEmpty(responses)){
            responses.forEach(o ->{
                o.setStatusName(ReturnGoodsOuterStatusEnum.getMessage(o.getStatus()));
                o.setApplyTypeName(AfterSaleTypeEnum.RETURN.getMessage());
                o.setOrderTypeName(OrderTypeEnum.getNameByCode(o.getOrderType()));
            });
        }
        return Wrapper.success(new PageData<>(totalCount, responses));
    }

    /**
     * 执行外部工作流
     * @param entity 退货表
     * @param agree 同意
     */
    private void completeOuterTask(ReturnGoodsDO entity, Integer agree){
        TaskExecuteVO taskStartVO=new TaskExecuteVO();
        taskStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(entity.getOuterTaskType()));
        taskStartVO.setMemberId(entity.getMemberId());
        taskStartVO.setRoleId(entity.getRoleId());
        taskStartVO.setDataId(entity.getId());
        taskStartVO.setAgree(agree);
        taskStartVO.setTaskId(entity.getOuterTaskId());
        Wrapper<SimpleTaskCompleteVO> taskResult = processFeignService.completeSimpleTask(taskStartVO);
        if (taskResult == null || taskResult.getCode() != ResponseCode.SUCCESS.getCode()
                || null == taskResult.getData()) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_ERROR);
        }
        entity.setOuterStatus(taskResult.getData().getStatus());
        String taskId=taskResult.getData().getTaskId();
        entity.setOuterTaskId(StringUtils.hasLength(taskId)?taskId:Constants.WORK_FLOW_END_TASK_ID_TAG);
        entity.setOuterTaskStep(taskResult.getData().getStep());
        entity.setUpdateTime(System.currentTimeMillis());
    }

    /**
     * 执行-内部工作流
     * @param entity 退货表
     * @param agree 同意
     */
    private void completeInnerTask(ReturnGoodsDO entity, Integer agree){
        TaskExecuteVO taskStartVO=new TaskExecuteVO();
        taskStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(entity.getInnerTaskType()));
        taskStartVO.setMemberId(entity.getMemberId());
        taskStartVO.setRoleId(entity.getRoleId());
        taskStartVO.setDataId(entity.getId());
        taskStartVO.setAgree(agree);
        taskStartVO.setTaskId(entity.getInnerTaskId());
        Wrapper<SimpleTaskCompleteVO> taskResult = processFeignService.completeSimpleTask(taskStartVO);
        if (taskResult == null || taskResult.getCode() != ResponseCode.SUCCESS.getCode()
                || null == taskResult.getData()) {
            throw new BusinessException(ResponseCode.AS_WORKFLOW_ERROR);
        }
        entity.setInnerStatus(taskResult.getData().getStatus());
        String taskId=taskResult.getData().getTaskId();
        entity.setInnerTaskId(StringUtils.hasLength(taskId)?taskId:Constants.WORK_FLOW_END_TASK_ID_TAG);
        entity.setInnerTaskStep(taskResult.getData().getStep());
        entity.setUpdateTime(System.currentTimeMillis());
    }

    @Override
    public Wrapper<ReturnGoodsBatchDetailVO> getReturnGoodsDeliveryOrReceiveDetail(UserLoginCacheDTO sysUser, Long returnDeliveryId, boolean isSupplier) {
        ReturnDeliveryGoodsDO returnDeliveryGoodsDO = returnDeliveryGoodsRepository.findById(returnDeliveryId).orElse(null);
        if(returnDeliveryGoodsDO==null){
            return Wrapper.fail(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(returnDeliveryGoodsDO.getReturnId()).orElse(null);
        if (returnDO == null) {
            return Wrapper.fail(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        //校验数据权限
        if(isSupplier){
            if(!ParamVerifyUtils.isValidMember(sysUser,returnDO.getParentMemberId(),returnDO.getParentMemberRoleId())){
                return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
            }
        }else{
            if(!ParamVerifyUtils.isValidMember(sysUser,returnDO.getMemberId(),returnDO.getRoleId())){
                return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
            }
        }
        ReturnGoodsBatchDetailVO resultVO=new ReturnGoodsBatchDetailVO();
        resultVO.setApplyNo(returnDO.getApplyNo());
        resultVO.setReturnId(returnDO.getId());
        resultVO.setDeliveryType(returnDO.getReturnGoodsAddress().getDeliveryType());
        resultVO.setDeliveryOrderNo(returnDeliveryGoodsDO.getDeliveryOrderNo());
        resultVO.setOrderName("退货申请单");
        resultVO.setOrderType(returnDO.getOrderType());
        if(isSupplier){
         //供应商查询
            resultVO.setAddress(returnDO.getReturnGoodsAddress().getSendAddress());
            resultVO.setUserName(returnDO.getReturnGoodsAddress().getSendUserName());
            resultVO.setTel(returnDO.getReturnGoodsAddress().getSendUserTel());
            resultVO.setMemberName(returnDO.getConsumerName());
            resultVO.setOrderTypeName("退货收货单");
            if(returnDeliveryGoodsDO.getReturnReceiveGoodsBO()!=null) {
                resultVO.setOrderTime(returnDeliveryGoodsDO.getReturnReceiveGoodsBO().getStorageTime());
                resultVO.setRemark(returnDeliveryGoodsDO.getReturnReceiveGoodsBO().getRemark());
                resultVO.setOrderAbstract(returnDeliveryGoodsDO.getReturnReceiveGoodsBO().getOrderAbstract());
                resultVO.setInventoryName(returnDeliveryGoodsDO.getReturnReceiveGoodsBO().getInventoryName());
                resultVO.setInventoryRole(returnDeliveryGoodsDO.getReturnReceiveGoodsBO().getInventoryRole());
            }
        }else{
         //采购商查询
            resultVO.setAddress(returnDO.getReturnGoodsAddress().getReceiveAddress());
            resultVO.setUserName(returnDO.getReturnGoodsAddress().getReceiveUserName());
            resultVO.setTel(returnDO.getReturnGoodsAddress().getReceiveUserTel());
            resultVO.setMemberName(returnDO.getSupplierName());
            resultVO.setOrderTypeName("退货发货单");
            resultVO.setOrderTime(returnDeliveryGoodsDO.getDeliveryTime());
            resultVO.setRemark(returnDeliveryGoodsDO.getRemark());
            resultVO.setOrderAbstract(returnDeliveryGoodsDO.getOrderAbstract());
            resultVO.setInventoryName(returnDeliveryGoodsDO.getInventoryName());
            resultVO.setInventoryRole(returnDeliveryGoodsDO.getInventoryRole());
        }
        List<ReturnGoodsDetailDO> goodsList = returnGoodsDetailRepository.findByReturnId(returnDO.getId());
        if(CollectionUtil.isEmpty(goodsList)){
            return Wrapper.fail(ResponseCode.AS_RETURN_GOODS_DETAIL_NOT_EXIST);
        }
        Map<String, ReturnGoodsDetailDO> goodsMap = goodsList.stream().collect(Collectors.toMap(o -> o.getOrderNo() + ":" + o.getProductId(), o -> o, (o1, o2) -> o1));
        List<ReturnGoodsBatchDetailProductVO> detailProductVOS = returnDeliveryGoodsDO.getDetailList().stream().map(o -> {
            ReturnGoodsBatchDetailProductVO vo = new ReturnGoodsBatchDetailProductVO();
            BeanUtils.copyProperties(o, vo);
            vo.setReturnDeliveryCount(o.getDeliveryCount());
            ReturnGoodsDetailDO returnGoodsDetailDO = goodsMap.get(o.getOrderNo() + ":" + o.getProductId());
            if (returnGoodsDetailDO != null) {
                vo.setIsNeedReturn(returnGoodsDetailDO.getIsNeedReturn());
                vo.setNeedReturnName(CommonBooleanEnum.getMessage(returnGoodsDetailDO.getIsNeedReturn()));
                vo.setRefundAmount(NumberUtil.mul(o.getDeliveryCount(), returnGoodsDetailDO.getPurchasePrice()));
                vo.setOrderId(returnGoodsDetailDO.getOrderId());
                vo.setReturnGoodsId(returnGoodsDetailDO.getId());
                vo.setReturnCount(returnGoodsDetailDO.getReturnCount());
                vo.setPurchasePrice(returnGoodsDetailDO.getPurchasePrice());
                vo.setType(returnGoodsDetailDO.getType());
                vo.setReturnDetailId(returnGoodsDetailDO.getId());
            }
            return vo;
        }).collect(Collectors.toList());
        resultVO.setGoodsDetailDeliveryList(detailProductVOS);
        return Wrapper.success(resultVO);
    }

    @Transactional
    @Override
    public Wrapper<Void> stopReturnGoods(UserLoginCacheDTO sysUser, ReturnGoodsStopVO stopVO) {
        ReturnGoodsDO returnDO = returnRepository.findById(stopVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        //非【不接受申请、售后完成、已中止】3种状态下可中止售后
        if (!ReturnGoodsOuterStatusEnum.isEnabledStop(returnDO.getOuterStatus())) {
            throw new BusinessException(ResponseCode.AS_RETURN_UN_ALLOW_STOP);
        }
        int oldStatus=returnDO.getOuterStatus();
        //更新状态
        returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.STOPPED.getCode());
        returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.STOPPED.getCode());
        returnDO.setUpdateTime(System.currentTimeMillis());
        returnRepository.saveAndFlush(returnDO);
        // 新增供应商外部流转记录
        addOuterWorkflowRecord(sysUser, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsOuterStatusEnum.getMessage(returnDO.getOuterStatus()), ReplaceGoodsHelpEnum.STOPPED.getMessage(), stopVO.getRemark());
        // 新增供应内部流转记录
        addInnerWorkflowRecord(sysUser, returnDO.getId(), returnDO.getInnerStatus(), ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus()), ReplaceGoodsHelpEnum.STOPPED.getMessage(), stopVO.getRemark());
        //对应首页统计计数-1
        commonReduceOperateNotice(returnDO,oldStatus);
        return Wrapper.success();
    }

    /**
     * 公共增加计数统计与操作通知
     * @param returnDO 退货表
     * @param status 状态
     */
    private void commonSystemMessageAndIncreaseOperateNotice(ReturnGoodsDO returnDO,Integer status){
        OperateNoticeVO noticeVO =null;
        //待平台审核退货申请单
        if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode())) {
            //待平台确认退货申请单(平台)+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(MemberRoleEnum.PLATFORM.getMemberId());
            noticeVO.setRoleId(MemberRoleEnum.PLATFORM.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.PLATFORM_AFTER_SALE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnPfHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增[待确认退货申请单]消息通知
            sendSystemMessage(MemberRoleEnum.PLATFORM.getMemberId(),MemberRoleEnum.PLATFORM.getRoleId(),MessageTemplateCode.return_goods_handle_platform_confirm,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }
        //待新增退货发货单
        else if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode())) {
            //待新增发货单
            //待售后退货申请(采购商)新增退货发货单+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增[待新增退货发货单]消息通知
            sendSystemMessage(returnDO.getMemberId(),returnDO.getRoleId(),MessageTemplateCode.return_goods_shipment,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if (status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode())) {
            //待确认发货
            //待售后退货申请(采购商)退货发货+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增[待确认售后完成]消息通知
            sendSystemMessage(returnDO.getMemberId(),returnDO.getRoleId(),MessageTemplateCode.return_goods_return_shipment,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode())){
            //待退货收货
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增[待退货收货]消息通知
            sendSystemMessage(returnDO.getParentMemberId(),returnDO.getParentMemberRoleId(),MessageTemplateCode.return_goods_handle_return_receive,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode())){
            //待确认退货回单
            // 售后退货申请(采购商)确认退货回单+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增[待确认退货回单]消息通知
            sendSystemMessage(returnDO.getMemberId(),returnDO.getRoleId(),MessageTemplateCode.return_goods_confirm_return,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode())){
            //待退款
            // 售后退货处理(供应商)待退款+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增供应商待退款消息通知
            sendSystemMessage(returnDO.getParentMemberId(),returnDO.getParentMemberRoleId(),MessageTemplateCode.return_goods_handle_refund,returnDO.getApplyNo(),returnDO.getApplyAbstract());
            // 新增[平台待退款]消息通知
            sendSystemMessage(MemberRoleEnum.PLATFORM.getMemberId(),MemberRoleEnum.PLATFORM.getRoleId(),MessageTemplateCode.return_goods_handle_platform_refund,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode())){
            //待确认退款
            // 售后退货处理(采购商)待确认退款+1
            noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setIncreaseOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setIncreaseTitle(returnDO.getApplyAbstract());
            noticeVO.setIncreaseDataId(returnDO.getId());
            feignService.addSysOperateNotice(noticeVO);
            // 新增供应商待确认退款消息通知
            sendSystemMessage(returnDO.getMemberId(),returnDO.getRoleId(),MessageTemplateCode.return_goods_confirm_refund,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }else if(status.equals(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode())){
            //待确认售后完成
            // 售后退货申请(采购商)确认售后完成+1
            noticeStatistics(returnDO);
            // 新增[待确认售后完成]消息通知
            sendSystemMessage(returnDO.getMemberId(),returnDO.getRoleId(),MessageTemplateCode.return_goods_confirm,returnDO.getApplyNo(),returnDO.getApplyAbstract());
        }
    }

    /**
     * 公共减少计数统计
     * @param returnDO 退货表
     * @param oldStatus 旧状态
     */
    private void commonReduceOperateNotice(ReturnGoodsDO returnDO,Integer oldStatus){
        logger.info("commonReduceOperateNotice: oldStatus:{}",oldStatus);
        OperateNoticeVO noticeVO = new OperateNoticeVO();
        if(ReturnGoodsOuterStatusEnum.TO_BE_SUBMIT.getCode().equals(oldStatus)){
            //待提交申请单
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM.getCode().equals(oldStatus)){
            //待确认申请单
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode().equals(oldStatus)){
            //待平台确认申请单
            noticeVO.setMemberId(MemberRoleEnum.PLATFORM.getMemberId());
            noticeVO.setRoleId(MemberRoleEnum.PLATFORM.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.PLATFORM_AFTER_SALE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnPfHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        }else if(ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode().equals(oldStatus)){
            //不接受申请
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_COMMIT.getCode());
        }else if(ReturnGoodsOuterStatusEnum.ACCEPT_APPLY.getCode().equals(oldStatus)){
            //接受申请
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_CONFIRM.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待新增退货发货单（确认申请单后）
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_DELIVERY.getCode());
        }else if(ReturnGoodsOuterStatusEnum.CONSUMER_TO_BE_ADD_LOGISTICS.getCode().equals(oldStatus)){
            //采购商待新增物流单
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_ADD_LOGISTICS.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(oldStatus)){
            //待退货发货
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_DELIVERY.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_GOODS_STORAGE.getCode().equals(oldStatus)){
            //待新增退货入库单
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_ADD_STORAGE.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_RETURN_RECEIVE_GOODS.getCode().equals(oldStatus)){
            //待退货收货
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_RECEIVE.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_RETURN_GOODS_RECEIPT.getCode().equals(oldStatus)){
            //待确认退货回单
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_RECEIPT.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(oldStatus)){
            //待退款
            noticeVO.setMemberId(returnDO.getParentMemberId());
            noticeVO.setRoleId(returnDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_HANDLE.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnHandleOperateTypeEnum.TO_BE_REFUND.getCode());
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_REFUND.getCode().equals(oldStatus)){
            //待确认退款(退款)
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_REFUND.getCode());
        }else if(ReturnGoodsOuterStatusEnum.CONFIRM_REFUND_FAIL.getCode().equals(oldStatus)){
            //确认退款未到账
        }else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(oldStatus)){
            //待确认售后完成
            noticeVO.setMemberId(returnDO.getMemberId());
            noticeVO.setRoleId(returnDO.getRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.AFTER_SALE_RETURN_APPLY.getCode());
            noticeVO.setReduceOperateType(AfterSaleReturnApplyOperateTypeEnum.TO_BE_CONFIRM_COMPLETE.getCode());
        }else if(ReturnGoodsOuterStatusEnum.COMPLETE.getCode().equals(oldStatus)){
            //售后完成
        }else if(ReturnGoodsOuterStatusEnum.STOPPED.getCode().equals(oldStatus)){
            //中止
        }

        if(noticeVO.getMemberId()!=null) {
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceDataId(returnDO.getId());
            logger.info("commonReduceOperateNotice: oldStatus:{},noticeVO:{}",oldStatus,JSONUtil.toJsonStr(noticeVO));
            feignService.addSysOperateNotice(noticeVO);
        }
    }

    public Wrapper<List<ReturnGoodsTaxVO>> getOrderDetailList(ReturnDetailReqVO req) {
        QReturnGoodsDetailDO returnGoodsDetailDO=QReturnGoodsDetailDO.returnGoodsDetailDO;
        QReturnGoodsDO returnGoodsDO=QReturnGoodsDO.returnGoodsDO;

        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        //退货详情中订单id
        if(CollectionUtil.isNotEmpty(req.getOrderIds())){
            predicates.and(returnGoodsDetailDO.orderId.in(req.getOrderIds()));
        }
        //退货详情中skuId
        if(CollectionUtil.isNotEmpty(req.getSkuIds())){
            predicates.and(returnGoodsDetailDO.skuId.in(req.getSkuIds()));
        }
        JPAQuery<ReturnGoodsTaxVO> data = jpaQueryFactory
                .select(Projections.constructor(ReturnGoodsTaxVO.class,
                        returnGoodsDetailDO.orderId,
                        returnGoodsDetailDO.skuId,
                        returnGoodsDO.outerStatus,
                        returnGoodsDetailDO.isHasTax,
                        returnGoodsDetailDO.taxRate,
                        returnGoodsDetailDO.purchasePrice,
                        returnGoodsDetailDO.purchasePrice,
                        returnGoodsDetailDO.purchaseCount
                ))
                .from(returnGoodsDetailDO)
                .leftJoin(returnGoodsDO)
                .on(returnGoodsDetailDO.returnId.eq(returnGoodsDO.id))
                .where(predicates);
        List<ReturnGoodsTaxVO> fetch = data.fetch();
        if(CollectionUtil.isNotEmpty(fetch)){
            fetch.forEach(o -> o.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(o.getOuterStatus())));
        }
        return Wrapper.success(fetch);
    }

    @Override
    public Wrapper<List<ReturnGoodsTaxVO>> getOrderInfoListByIdsAndSkuIds(ReturnDetailReqVO req) {
        return getOrderDetailList(req);
    }


}
